form-data类型
def multipart_producer(boundary, filename): """构建 multipart, 返回 yield, 实现分片上传""" import time,chardet,os,mimetypes def _encode(_str): if not _str.strip(): return _str if isinstance(_str, unicode): return _str.encode('utf-8') encoding = chardet.detect(_str).get('encoding') or 'utf-8' # print _str, encoding return _str.decode(encoding).encode('utf-8', 'ignore') boundary_bytes = boundary.encode() filename_bytes = _encode(filename) start = time.time() file_size = os.path.getsize(filename) file_size_mb = round(float(file_size) / 1024 / 1024, 2) mtype = mimetypes.guess_type(filename)[0] or "application/octet-stream" buf = ( (b"--%s\r\n" % boundary_bytes) + ( b'Content-Disposition: form-data; name="file"; filename="%s"\r\n' % (filename_bytes,) ) + (b"Content-Type: %s\r\n" % mtype.encode()) + b"\r\n" ) # print buf yield buf with open(filename, "rb") as f: while True: # 16k at a time. chunk = f.read(160 * 1024) # 打印上传进度 if time.time() - start > 5: start = time.time() print 'Total size: {} MB, Process {} %'.format( file_size_mb, round(float(f.tell()) / file_size * 100, 2) ) if not chunk: break yield chunk yield b"\r\n" yield b"--%s--\r\n" % (boundary_bytes,)
使用方法
boundary = uuid4().hex file_name = os.path.basename(path) print '开始上传 {}'.format(file_name) headers = { 'Content-Type': 'multipart/form-data; boundary={0}'.format(boundary), 'charset': 'UTF-8'} data = multipart_producer(boundary, path)