はじめに
swiftのPDFKitを使ったPDFビューアーを作る時に、httpでダウンロードしたファイルがPDFかどうかを判定する必要がありました。PDFの判定方法とswiftでの実装を書きます。
PDFの判定
Webサーバから、HTTPでダウンロードしたコンテンツがPDFか判定するのは、以下の2種類がありました。サーバからの応答メッセージ中のHTTPヘッダを見ることで、PDFか判定できそうです。
- Content-Type: ブラウザ中でPDFが表示される
- Content-Disposition: PDFがダウンロードされる
1. Content-Type
ブラウザでPDFが表示されるパターンです。HTTPヘッダには、以下の文字列が存在しています。このヘッダが存在する時には、PDFファイルと認識できます。
Content-Type: application/pdf
2. Content-Disposition
ブラウザでPDFがダウンロードされるパターンです。HTTPヘッダには、以下の文字列が存在しています。ファイルの拡張子が.pdf
の場合に、PDFファイルと認識することにします。
Content-Disposition:attachment;filename='downloaded.pdf'
SWIFTでの実装
上記のPDF判定をSWIFTで記載したコードです。以下の開発環境での動作は確認しています。
開発環境
このコードの実装環境は以下です。
- Xcode : 11.1
- iOS : 13.2
PDF判定コード
URLを引数に渡し、戻り値でPDFの判定をするコードです。semaphoreを使って、PDF判定が完了してから判定結果を戻り値で戻します。webサーバからの応答を待つので、Mainスレッドで使えるコードではありません。必要があれば、semaphoreをやめて、非同期で実装してください。
private func isPdf(url: URL) -> (Bool) {
var result: Bool = false
var request = URLRequest(url: url)
request.httpMethod = "HEAD"
let semaphore = DispatchSemaphore(value: 0)
URLSession.shared.dataTask(with: request) { (data, urlResponse, error) in
guard let urlResponse = urlResponse as? HTTPURLResponse else {
// レスポンスなし
result = false
semaphore.signal()
return
}
if let contentType = urlResponse.allHeaderFields["Content-Type"] as? String {
if contentType.contains("application/pdf") {
result = true
semaphore.signal()
return
}
}
if let contentDisposition = urlResponse.allHeaderFields["Content-Disposition"] as? String {
if contentDisposition.contains(".pdf") {
result = true
semaphore.signal()
return
}
}
result = false
semaphore.signal()
}.resume()
semaphore.wait()
return result
}