Swift MIME Type Detection with Swime
A month ago I found myself scouring GitHub for a Swift plugin to detect mime type based on magic bytes. I did find MimeType, unfortunately it extracts the mime type from a file path or url extension. Knowing that no one hadn't created a mime type checking library for Swift, I set a to-do list to learn about mime type checking, hoping that I could contribute to the open source community. My first attempt was to understand how to read file bytes in Swift. Below is my best attempt after going through Apple docs and some examples from stackoverflow.
let path = "/path/to/file"
let url = URL(fileURLWithPath: path, isDirectory: false)
let data = try! Data(contentsOf: url)
Okay now I've got the file represented in Data
struct, how do I read the bytes?
It turns out we need to allocate an array of UInt8
as the bytes container
then pass it to Data.copyBytes(to:count:)
let bytesCount = 10
// Bytes need to mutable.
var bytes = [UInt8](repeating: 0, count: bytesCount)
// Copy file bytes to `bytes` variable
data.copyBytes(to: &bytes, count: bytesCount)
Next is the hard part, some of the magic bytes specification
need to be treated differently, for example we need to read bytes 0-3 then jump to bytes 30-57 to check
for application/epub+zip
.
Swime comes to aid this. I took the awesome implementation of
Sindresorhus file type library and rewrote it in Swift with
some added features.
A typical mime type check operation with Swime would look like this
import Swime
let path = "/path/to/some-file.jpg"
let url = URL(fileURLWithPath: path, isDirectory: false)
let data = try! Data(contentsOf: url)
let mimeType = Swime.mimeType(data: data)
mimeType?.type == .jpg // true
mimeType! // MimeType(mime: "image/jpeg", ext: "jpg", type: .jpg)
switch mimeType?.type {
case .jpg?:
....
case .png?:
....
case .wmv?:
....
case ...
}
Please feel free to open an issue or pull request if there's a feature that would be a great addition to Swime!