Skip to content

Commit

Permalink
feat(storage): fill content-type based on file extension (#400)
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev authored May 27, 2024
1 parent db7a094 commit 569f445
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 12 deletions.
53 changes: 53 additions & 0 deletions Sources/Storage/Helpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Helpers.swift
//
//
// Created by Guilherme Souza on 22/05/24.
//

import Foundation

#if canImport(CoreServices)
import CoreServices
#endif

#if canImport(UniformTypeIdentifiers)
import UniformTypeIdentifiers
#endif

#if os(Linux) || os(Windows)
/// On Linux or Windows this method always returns `application/octet-stream`.
func mimeTypeForExtension(_: String) -> String {
"application/octet-stream"
}
#else
func mimeTypeForExtension(_ fileExtension: String) -> String {
if #available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, visionOS 1.0, *) {
return UTType(filenameExtension: fileExtension)?.preferredMIMEType ?? "application/octet-stream"
} else {
guard
let type = UTTypeCreatePreferredIdentifierForTag(
kUTTagClassFilenameExtension,
fileExtension as NSString,
nil
)?.takeUnretainedValue(),
let mimeType = UTTypeCopyPreferredTagWithClass(
type,
kUTTagClassMIMEType
)?.takeUnretainedValue()
else { return "application/octet-stream" }

return mimeType as String
}
}
#endif

extension String {
var pathExtension: String {
(self as NSString).pathExtension
}

var fileName: String {
(self as NSString).lastPathComponent
}
}
12 changes: 4 additions & 8 deletions Sources/Storage/StorageFileApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ public class StorageFileApi: StorageApi {
file: Data,
options: FileOptions
) async throws -> FileUploadResponse {
let contentType = options.contentType
let contentType = options.contentType ?? mimeTypeForExtension(path.pathExtension)
var headers = HTTPHeaders([
"x-upsert": "\(options.upsert)",
])

headers["duplex"] = options.duplex

let fileName = fileName(fromPath: path)
let fileName = path.fileName

let form = FormData()
form.append(
Expand Down Expand Up @@ -474,13 +474,13 @@ public class StorageFileApi: StorageApi {
file: Data,
options: FileOptions = FileOptions()
) async throws -> SignedURLUploadResponse {
let contentType = options.contentType
let contentType = options.contentType ?? mimeTypeForExtension(path.pathExtension)
var headers = HTTPHeaders([
"x-upsert": "\(options.upsert)",
])
headers["duplex"] = options.duplex

let fileName = fileName(fromPath: path)
let fileName = path.fileName

let form = FormData()
form.append(file: File(
Expand Down Expand Up @@ -511,7 +511,3 @@ public class StorageFileApi: StorageApi {
return SignedURLUploadResponse(path: path, fullPath: fullPath)
}
}

private func fileName(fromPath path: String) -> String {
(path as NSString).lastPathComponent
}
7 changes: 3 additions & 4 deletions Sources/Storage/Types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ public struct FileOptions: Sendable {
/// in the `Cache-Control: max-age=<seconds>` header. Defaults to 3600 seconds.
public var cacheControl: String

/// The `Content-Type` header value. Should be specified if using a `fileBody` that is neither
/// `Blob` nor `File` nor `FormData`, otherwise will default to `text/plain;charset=UTF-8`.
public var contentType: String
/// The `Content-Type` header value.
public var contentType: String?

/// When upsert is set to true, the file is overwritten if it exists. When set to false, an error
/// is thrown if the object already exists. Defaults to false.
Expand All @@ -59,7 +58,7 @@ public struct FileOptions: Sendable {

public init(
cacheControl: String = "3600",
contentType: String = "text/plain;charset=UTF-8",
contentType: String? = nil,
upsert: Bool = false,
duplex: String? = nil
) {
Expand Down

0 comments on commit 569f445

Please sign in to comment.