Skip to content

feat(storage): fill content-type based on file extension #400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -472,13 +472,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 @@ -509,7 +509,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
Loading