フォト蔵APIのPython wrapperを作る Vol.2 multipart/form-data
前回からの続きです。
フォト蔵APIのPython wrapperを作る Vol.1 Basic認証 - hachi's blog
multipart/form-data
さあ、認証も通ったのでいよいよ写真のアップしてみましょう。 しかし、写真をアップロードするためには、multipart/form-dataを使う必要があります。 multipart/form-dataとは、テキストデータと画像などのバイナリデータをバウンダリで区切って まとめてサーバに送る方法です。 詳しくは RFC 2388 を読んでください。
残念ながら、Pythonの標準ライブラリだけではこのmultipart/form-dataでデータをPOSTすることができません。 PyPIにはMultipartPostHandlerっていうライブラリもあるのですが、 今回はこれは使わずに自分で実装していきます。
例によって、うだうだ説明するよりソース読んだほうが分かりやすいでしょ。
#!/usr/bin/env python import httplib import mimetypes boundary = '-----photozou.py-----' disposition = 'Content-Disposition: form-data; name="%s"' #アップロードする写真のデータ values = open(file_name, 'rb').read() #写真の情報 data = {} data['album_id'] = album_id data['photo_title'] = photo_title data['description'] = description data['tag'] = tag data['comment'] = comment data['data_type'] = data_type data['year'] = year data['month'] = month data['day'] = day #送信するbodyを作る lines = [] lines.append('--' + boundary) lines.append(disposition % 'photo' + '; filename="%s"' % file_name) lines.append('Content-Type: %s' % mimetypes.guess_type(file_name)[0]) lines.append('') lines.append(values) for k, v in data.iteritems(): lines.append('--' + boundary) lines.append(disposition % k) lines.append('') lines.append(v) lines.append('--' + boundary + '--') lines.append('') data_str = '\r\n'.join(lines) #ヘッダを作る header = {'Authorization' : 'Basic %s' % auth_info} header['Content-Type'] = 'multipart/form-data; boundary=%s' % boundary conn = httplib.HTTPConnection('api.photozou.jp') conn.request('POST', '/rest/photo_add/', data_str, header) res = conn.getresponse() print res.status, res.reason print res.read()
辞書に格納したデータをバウンダリで区切りながらbodyの文字列を作っていきます。 画像ファイルの場合は、ファイル名を書いたり、mimetypeを指定したりしなきゃダメみたいです。 大事なポイントとしては、バウンダリをbodyに追加するときは先頭に'--'を付加するって事。 そして最後のバウンダリは先頭と最後に'--'を付加する必要ありです。 それと改行コードがCRLFって事。
そんなこんなで
写真をアップロードするという最大の山場を越えましたので、 後はぼちぼちと他の機能をラップしていくだけです。 全APIをラップできたら、それ使ったアプリもつくりたいですね。
参考ページ
urllib2のみでmultipart/form-dataを送る - YAMAGUCHI::weblog
Http client to POST using multipart/form-data « Python recipes « ActiveState Code