LoginSignup
1
1

More than 1 year has passed since last update.

swiftでDropbox API用にヘッダに日本語ファイル名があるデータをポストする

Last updated at Posted at 2021-07-07

iPhoneからDropboxにファイルをアップロードしようとしてDropbox API を調べながらやってみた。

準備

ユーザ登録とかアプリの登録とかアクセストークンの発行とかあるけど、まあDropox APIのページに書いてあるとおりやればいい。見たら、すでにアプリの登録までやってあった。昔にラズパイからアップロードしようとした形跡(そういうアプリ名になっている)がある(^^;)。全然覚えてないし、、。

SwiftyDropboxで試す

swift用にSwiftyDropboxというSDK(?)があるけど、Tutorial通りやっても動かないので1時間くらいで諦める。

直接URLを叩く

URLを叩くだけなので、公式のページ(upload だとこの辺)に結構親切に書いてある通りにやる。

curlでやってみる

とりあえず curl の例が出ているのでそのままコピペすると動く。

curl -X POST https://content.dropboxapi.com/2/files/upload \
    --header "Authorization: Bearer <get access token>" \
    --header "Dropbox-API-Arg: {\"path\": \"/Homework/math/Matrices.txt\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}" \
    --header "Content-Type: application/octet-stream" \
    --data-binary @local_file.txt

get access token のところは、本物はクリックするとアクセストークンが入ってくれる。

swiftで試しにやってみる

        // header
        request.addValue("Bearer <ここはアクセストークンが入る>", forHTTPHeaderField: "Authorization")
        request.addValue("{\"path\": \"/Homework/math/Matrices.txt\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}",forHTTPHeaderField: "Dropbox-API-Arg")
        request.addValue("application/octet-stream",forHTTPHeaderField: "Content-Type")
        // POSTするデータをBodyとして設定
        request.httpBody = "This is a pen.\n".data(using: .utf8)

        let session = URLSession.shared
        session.dataTask(with: request) { (data, response, error) in
            if error == nil, let data = data, let response = response as? HTTPURLResponse {
                // HTTPヘッダの取得
                print("Content-Type: \(response.allHeaderFields["Content-Type"] ?? "")")
                // HTTPステータスコード
                print("statusCode: \(response.statusCode)")
                print(String(data: data, encoding: .utf8) ?? "")
            }
        }.resume()

(どこかのサイトからコピペしましたが、今探しても見つかりませんでした。すみません。)
これでOK。

ちゃんとやってみる。

で、パス名とかをちゃんと治してみたら、パス名が英語だとうまくいくけど、日本語だとNG。(400で返ってくる。)
「そうか、encodeしないといけないのね。」と思って、URLエンコードしてみるけどうまく行かない。
「日本語」を「%E6%97%A5%E6%9C%AC%E8%AA%9E」とか書くと、そのままのファイルが出来てしまう。

(Macの)curlで試すと、日本語をUTF8(のファイル)で書いてもそのまま動く。
「encode しなくていいのか?」

だんだん分からなくなる。curlがどんなデータを渡しているのかわからないので、仕方ないので WireShark でパケットを見たら、UTF8 が直接流れている。

じゃあ、ということで swift のプログラムのパケットを見てみたら、日本語のパス名のところで切れている。どうも UTF8 のデータをうまく扱えていないみたいだ。で色々試してみたら、「日本語」を「\u65E5\u672C\u8A9E」って書いてあげると動くのが分かった。なので、

        // パス名に日本語が入っていると400で失敗する
        var encodedfname: String = ""
        for c in fname.utf16 {
            encodedfname = encodedfname + String(format: "\\u%04X",c)
        }

みたいに変換してあげると動いた。

もっと上手に encode してあげると良いのかもしれないけれど、とりあえず動いたのでOKとする。
なお、ヘッダではなくてURLの引数にパス名を入れる方法があるとは書いてあるけど、シンタックスが見つからなかったので試してません。それならURLエンコードでうまくいくような気がする。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1