废话不多说啦, 三个点:
Header
里面设置 Content-Type
;
Header
里面设置 Content-Length
;
- 把文件内容读出来, 按格式要求写到 Body 里面.
一、Content-Type
因为我们是通过 Post Form 的形式上传文件, 所以 Content-Type
是: multipart/form-data
.
1 2 3
| boundary = mimetools.choose_boundary() content_type = 'multipart/form-data; boundary=%s' % boundary
|
二、Body 格式
Content-Length
很简单, 只要构建好了 Body, Length 就是 len(Body)
怎么构建 Post 的 Body 部分呢?先创建一个 binary 对象: binary = io.BytesIO()
然后再往里面写东西就好啦. 不过写的时候注意按以下格式.
2.1 先创建一个分割线
1 2
| part_boundary = '--' + boundary
|
2.2 构建 Form 表单每一个常规 Field
常规 Field 只有 name
和 value
.
1 2 3 4 5 6 7 8 9 10 11
| regular_blocks = [] for name, value in regular_fields.items(): block = [part_boundary, 'Content-Disposition: form-data; name="%s"' % name, '', value ] block = '\r\n'.join(block) block = codecs.encode(block) regular_blocks.append(block) regular_blocks = '\r\n'.join(regular_blocks)
|
2.3 构建 Form 表单每一个文件 Field
文件 Field 有 field_name
, file_name
, file_type
和 file_data
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| file_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
with codecs.open(file_path, 'rb') as f: file_data = f.read() ...
file_blocks = [] for field_name, file_name, file_type, file_data in file_fields: block = [part_boundary, 'Content-Disposition: form-data; name="%s"; filename="%s"' % (field_name, file_name), 'Content-Type: %s' % file_type, '', file_data ] block = '\r\n'.join(block) file_blocks.append(block) file_blocks = '\r\n'.join(file_blocks)
|
2.4 把这些 blocks 写入 binary
1 2 3
| all_field_blocks = '\r\n'.join(regular_blocks, file_blocks) binary.write(all_field_blocks) binary.write('\r\n--' + boundary + '--\r\n')
|
2.5 得到 Body
1
| body = str(binary.getvalue())
|
三、Content-Length
Content-Length 就是 len(body)
四. 发送数据
1 2 3 4 5 6 7 8 9 10
| from urllib2 import Request from urllib2 import urlopen from urllib2 import HTTPError ...
headers = {'Content-Length': len(body)), 'Content-Type': `multipart/form-data; boundary=%s` % mimetools.choose_boundary()} upload_req = Request(url=upload_url, data=body, headers=headers) upload_rep = urlopen(upload_req).read() print(upload_rep)
|