フォト蔵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