iOSでdropbox連携を行う(第4回)

2018年、明けましておめでとうございます。E-kanのラボ主です。
おそらく、新年一発目の記事投稿だと思うので、新年の挨拶をしてみました。
昨年は投稿頻度も記事の内容も中途半端だったので、今年は頻度を上げて充実な内容の記事投稿を心掛けたいと思います。

iOSでdropboxのファイルをダウンロード

さて、そんな新年一発目の記事は…
もの凄く間が空いてしまっていた、iOSのdropbox連携の連載第4回です。
前回は3.5回だったので、実質は5回目でしょうか?
前回までで、Dropboxのファイルリストまで取れるようになりました。覚えてますか?
今回はファイルをダウンロードして、表示してみたいと思います。
と言っても、いきなりPDFとかwordとかExcelとかを表示できるようにするのは厳しいので、
単純なテキストファイルを表示してみます。
(と言うか、wordとかExcelって自前での表示は厳しいきがする)

1. 事前準備

まずは事前準備として、dropboxにテキストファイルを入れて置かないとダウンロードできないので、トップディレクトリに適当なテキストファイルを配置してください。
1点注意ですが、この時にUTF8で保存したファイルを入れるようにして下さい。
他のコードで保存している場合は、ダウンロード後の表示で文字化けしてしまいます。

私は下の内容のファイルを作りました。

test.txt
dropboxダウンロード
テストです。

以下ではこの test.txt をダウンロードして行きます。

2. ファイルのダウンロードメソッド

ダウンロードファイルが作成できたので、次は実装するメソッドを調べます。
と言っても、公式マニュアルに Download-style request という項があるので、これを使うだけです。ですが、マニュアルには2つのメソッドが載っています。

client.files.download(path: “/path”, overwrite: true, destination: destination)
client.files.download(path: "/path")

1つ目はファイルをダウンロードして、端末に保存するメソッドで、
2つ目はファイルをダウンロードして、メモリ上に読み込むメソッドのようです。
ソーシャルゲームみたいに、データを端末にダウンロードする場合は1つ目を使って、
すぐにファイルを表示して端末に保存する必要がない場合は2つ目を使う、
というような使い分けになりそうです。

3. ダウンロードの実装

それでは実際に実装をしていきます。
今回は、端末に保存する必要がないので、前項の2つ目のメソッドを実装します。
ViewController.swift に次のコードを追加しましょう。

    @IBAction func pushDownload(_ sender: Any){
        let path = "/test.txt"
        guard let client = DropboxClientsManager.authorizedClient else {
            print(“認証されていません”)
            return
        }
        client.files.download(path: path).response { (response, error) in
            if let response = response {
                print(response)
            } else if let error = error {
                print(error)
            } else {
                print("response and error is nil")
            }
        }.progress { (progress) in
            print(progress)
        }
    }

画面のボタンを押したら実行させたいので、IBでボタンと関連付けできるように@IBActionを付けています。
また、dropboxの認証が行われていない(あるいは期限切れ)場合もあるので、その場合は”認証されていません”をログに出力する様にしています。

次は、画面にダウンロードボタンを追加しましょう。
Main.storyboardを開いて、UIButtonをドラッグして追加、ボタン名を適当に変更して、
ViewControllerのpushDownloadをボタンのTouchUpInsideに関連付けます。
(詳しいやり方は、連載の2回目かどこかのWEBサイトを参照ください)

さて、これでダウンロードの実装完了です。
それでは、実際に動かして観ましょう!
こんな感じのログが出て来たら成功です。

<NSProgress: 0x60000012d2a0> : Parent: 0x0 / Fraction completed: 1.0000 / Completed: 44 of 44  
({
    "client_modified" = "2017-12-31T09:32:53Z";
    "content_hash" = a7188a8df4cffdbf1cb7bfe9ab33b5d7997f3f9c80e2a6b087c5fe8b2ef7968f;
    id = "id:bLMfqIGYb7MAAAAAAAAOEQ";
    name = "test.txt";
    "path_display" = "/test.txt";
    "path_lower" = "/test.txt";
    rev = cc0647110c;
    "server_modified" = "2017-12-31T09:32:53Z";
    size = 44;
}, 44 bytes)

もし、”認証されていません”と出たら、一度認証ボタンで認証を行ってください。

4. テキストの表示

続いて、ダウンロードデータをテキストに変換して出力しましょう。
前項では response を得ただけで、実際のデータは見れていなかったので、responseメソッド内のブロック部分を次の様に変えてみましょう。

            if let response = response {
                let responseMetadata = response.0
                print(responseMetadata)
                let text = String(data: response.1, encoding: .utf8)
                print(text ?? "empty")
            } else if let error = error {
                print(error)
            } else {
                print("response and error is nil")
            }

これを実行して、次の様なログが出れば成功です。

(---略---)
dropboxダウンロード
テストです。

少し解説しますと、
response.0 はファイルのメタデータ、response.1 は実データが入っています。
response.1 をファイル形式に応じて処理していく訳ですが、
今回はテキストデータ固定と決め打ちして、UTF8エンコードで文字列に変換して、ログに出力しています。
ちなみに、dropboxに入れたテキストファイルがUTF8以外の文字コードで保存されている場合は、文字化けしますので注意して下さい。
その場合は、.utf8 の部分を .shiftJIS などの保存した文字コードに変えると上手く行きます。

5. エラー

ここまでで、今回の目的となるテキストファイルのダウンロードと表示は完了です。
最後に、私が今回試したエラーを紹介します。
・ファイルが無い(パス誤り)

<NSProgress: 0x604000131800> : Parent: 0x0 / Fraction completed: 0.0000 / Completed: 97 of -1  
[request-id 750f5b0c170eda099b9b6ee9df53c064] API route error - {
    ".tag" = path;
    path =     {
        ".tag" = "not_found";
    };
}

存在しないファイルをダウンロードしようとすると、こんなエラーが発生しました。
・パスの先頭に”/“がない
ダウンロードのファイルパスを”test.txt”のようにして、頭に”/“を忘れると、downloadメソッドでパターンエラーとなってクラッシュしました。
・通信エラー(ネットワーク切断)

Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSErrorFailingURLStringKey=https://api-content.dropbox.com/2/files/download, NSErrorFailingURLKey=https://api-content.dropbox.com/2/files/download, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=60, NSLocalizedDescription=The request timed out.}

ネットワークを切断した時のエラーはよくみるエラーでした。

次回はアップロード

これでiOSでのdropbox連携の連載4回目が終了です。
今回やったのはテキストファイルだけですが、ダウンロードデータはData型で取得できるので、今回のやり方でどんなファイルでも対応できると思います。

次回は、基本機能の1つであるファイルのアップロードをやってみたいと思います。
なるべく期間を空けずに書こうと思いますので、暫くお待ちください。

Posted in システム開発 and tagged , , .