Swift implementation of RFC 7578: Returning Values from Forms - multipart/form-data
This package provides a Swift implementation of multipart/form-data as defined in RFC 7578. It enables creating multipart/form-data messages for HTTP file uploads with proper Content-Disposition header escaping and binary data support.
RFC 7578 specifies the multipart/form-data media type for submitting forms and uploading files in HTTP requests.
- Multipart/Form-Data: Create form-data messages with fields and file uploads
- Binary File Support: Direct binary data support (no encoding needed per RFC 7578 §4.7)
- Content-Disposition Escaping: Proper escaping of field names and filenames
- Type-Safe File Upload: Validated file upload structure with required field names and filenames
- RFC Compliant: Follows RFC 7578 specifications for HTTP form data
- Swift 6 Support: Strict concurrency support with full
SendableandCodableconformance
Add swift-rfc-7578 to your package dependencies:
dependencies: [
.package(url: "https://github.com/swift-standards/swift-rfc-7578.git", from: "0.1.0")
]Then add it to your target:
.target(
name: "YourTarget",
dependencies: [
.product(name: "RFC 7578", package: "swift-rfc-7578")
]
)import RFC_2046
import RFC_7578
// Create form data with text fields
let formData = try RFC_2046.Multipart.formData(
fields: [
"username": "john_doe",
"email": "[email protected]"
]
)
// Get Content-Type header
let contentType = formData.contentType.headerValue
// "multipart/form-data; boundary=----=_Part_<UUID>"
// Render the complete form data body
let body = formData.render()import Foundation
import RFC_2045
import RFC_2046
import RFC_7578
// Load image data
let imageData = try Data(contentsOf: URL(fileURLWithPath: "photo.jpg"))
// Create file upload
let file = try RFC_7578.FormData.File(
fieldName: "avatar",
filename: "photo.jpg",
contentType: RFC_2045.ContentType(type: "image", subtype: "jpeg"),
content: imageData
)
// Create form data with fields and files
let formData = try RFC_2046.Multipart.formData(
fields: [
"username": "john_doe",
"email": "[email protected]"
],
files: [file]
)
// Use in HTTP request
let contentType = formData.contentType.headerValue
let body = formData.render()let imageFile = try RFC_7578.FormData.File(
fieldName: "avatar",
filename: "photo.jpg",
contentType: RFC_2045.ContentType(type: "image", subtype: "jpeg"),
content: imageData
)
let documentFile = try RFC_7578.FormData.File(
fieldName: "document",
filename: "resume.pdf",
contentType: RFC_2045.ContentType(type: "application", subtype: "pdf"),
content: pdfData
)
let formData = try RFC_2046.Multipart.formData(
fields: ["description": "My files"],
files: [imageFile, documentFile]
)Represents a file upload in multipart/form-data.
public struct File {
public let fieldName: String
public let filename: String
public let contentType: RFC_2045.ContentType?
public let content: Data
public init(
fieldName: String,
filename: String,
contentType: RFC_2045.ContentType? = nil,
content: Data
) throws
}Creates a multipart/form-data message.
public static func formData(
fields: [String: String],
files: [RFC_7578.FormData.File] = [],
boundary: String? = nil
) throws -> RFC_2046.Multipart// Escape field names and filenames
let escaped = RFC_2046.Multipart.escapeContentDisposition(
name: "avatar",
filename: "photo.jpg"
)
// Result: "form-data; name=\"avatar\"; filename=\"photo.jpg\""
// Handles special characters
let escapedWithQuotes = RFC_2046.Multipart.escapeContentDisposition(
name: "field\"name"
)
// Result: "form-data; name=\"field\\\"name\""do {
let file = try RFC_7578.FormData.File(
fieldName: "", // Empty field name
filename: "photo.jpg",
content: imageData
)
} catch RFC_7578.FormData.Error.emptyFieldName {
print("Field name cannot be empty")
}
do {
let file = try RFC_7578.FormData.File(
fieldName: "avatar",
filename: "", // Empty filename
content: imageData
)
} catch RFC_7578.FormData.Error.emptyFilename {
print("Filename cannot be empty for file uploads")
}This implementation follows RFC 7578 specifications:
- Content-Disposition Headers: Each part includes proper
Content-Disposition: form-dataheaders - Field Name Requirements: Field names are required and properly escaped
- Filename Parameter: File uploads include the filename parameter
- Binary Data Support: Per RFC 7578 §4.7, Content-Transfer-Encoding is not used because HTTP supports binary data natively
- Character Escaping: Proper escaping of quotes in field names and filenames
- Swift 6.0+
- macOS 14.0+ / iOS 17.0+ / tvOS 17.0+ / watchOS 10.0+
- swift-rfc-2045 - MIME fundamentals (Content-Type, Content-Transfer-Encoding)
- swift-rfc-2046 - MIME multipart media types
- swift-rfc-2388 - Returning Values from Forms: multipart/form-data encoding
This library is released under the Apache License 2.0. See LICENSE for details.
Contributions are welcome! Please feel free to submit a Pull Request.