Python中如何在带参数的POST请求中同时上传文件?
嘿,我来帮你搞定这个文件上传的问题!首先得指出你原来代码里的一个小矛盾:你设置的Content-type是application/x-www-form-urlencoded,但Accept是multipart/form-data——要上传文件的话,请求体必须用multipart/form-data格式,而且Content-type头得包含一个用来分隔表单内容的边界字符串(boundary)。
下面是修改后的完整实现,我会一步步给你解释关键部分:
实现文件+表单参数的POST请求
首先我们需要构造符合multipart/form-data格式的请求体,把普通参数(par1、par2)和文件内容一起打包进去:
import httplib import random import string # 生成随机的boundary字符串,用来分隔表单中的不同部分(避免内容冲突) boundary = '----' + ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(16)) def build_multipart_formdata(fields, files): """构造multipart/form-data格式的请求体""" body_parts = [] # 添加普通表单参数(par1、par2这类) for field_name, field_value in fields.items(): body_parts.append(f'--{boundary}') body_parts.append(f'Content-Disposition: form-data; name="{field_name}"') body_parts.append('') # 空行分隔头和内容 body_parts.append(str(field_value)) # 添加文件内容 for file_field_name, file_info in files.items(): filename, file_content, content_type = file_info body_parts.append(f'--{boundary}') body_parts.append(f'Content-Disposition: form-data; name="{file_field_name}"; filename="{filename}"') body_parts.append(f'Content-Type: {content_type}') body_parts.append('') # 空行分隔头和文件内容 body_parts.append(file_content) # 结尾的边界标记 body_parts.append(f'--{boundary}--') body_parts.append('') # 用\r\n拼接所有部分(multipart格式要求的换行符) return '\r\n'.join(body_parts) # ---------------------- 替换成你自己的参数和文件信息 ---------------------- # 普通表单参数(par1、par2) form_fields = {'par1': '1', 'par2': '2'} # 文件信息:这里需要你替换成实际的文件路径、服务器接收文件的字段名、文件类型 file_field_name = 'upload_file' # 服务器端用来接收文件的字段名,比如后端用request.files['upload_file']获取 target_filename = 'example.txt' with open(target_filename, 'rb') as f: file_content = f.read() # 二进制读取文件,避免编码问题 file_info = (target_filename, file_content, 'text/plain') # 非文本文件要改Content-Type,比如图片用image/jpeg # 构造请求体 request_body = build_multipart_formdata(form_fields, {file_field_name: file_info}) # 设置正确的请求头 headers = { 'Content-Type': f'multipart/form-data; boundary={boundary}' # 如果服务器有特殊的Accept要求,再加上对应的Accept头即可 } # 发送请求(URL里的par3、par4保持不变) conn = httplib.HTTPConnection("somedomain.com") conn.request( method="POST", url="/cportal/public/api/edit?par3=3&par4=4", body=request_body, headers=headers ) # 可选:获取并处理响应 response = conn.getresponse() print(f"响应状态:{response.status} {response.reason}") print("响应内容:", response.read()) conn.close()
关键要点说明
- Boundary字符串:必须是一个不会出现在文件内容或表单参数里的随机字符串,用来告诉服务器哪里是一个字段的结束、下一个字段的开始。
- 请求头调整:原来的
application/x-www-form-urlencoded要替换成multipart/form-data; boundary=xxx,这是服务器识别文件上传请求的关键。 - 文件读取:用二进制模式
rb读取文件,确保非文本文件(比如图片、PDF)的内容不会被损坏。 - Content-Type适配:不同类型的文件要设置对应的Content-Type,比如图片用
image/png,PDF用application/pdf,如果不确定可以用application/octet-stream(通用二进制类型)。
内容的提问来源于stack exchange,提问作者user3260061
相关产品推荐
相关产品推荐

