解决python发送multipart/form-data请求上传文件的问题
服务器接收文件时,有时会使用表单接收的方式,这意味着我们需要使用Python的requests上传表单数据和文件。
常用的方式一般如下:
data = {
'name': 'nginx'
}
files = {'file': open("abc.csv", 'rb')}
response = requests.post(url, data=data, files=files)
files是封装好的参数,直接包括了文件内容,文件名,格式等,data则是表单内容,但这样做有一个问题,文件是中文名时,requests就会报错,哪怕encode转码成utf8也没用
百度发现除了requests的这个方法,还可以用一个第三方包MultipartEncoder,而这个包相对来说比较灵活。
一般是from requests_toolbelt.multipart.encoder import MultipartEncoder,这样导入使用
由于公司项目需要兼容各种环境,不主张使用大量第三方库,我精简模块后提取出my_compat 文件,变成 from my_compat import MultipartEncoder这样导入使用
但MultipartEncoder也存在无法转化中文名的问题,所以我在代码里取了巧,先把文件名转化成可解析的字符,然后用to_string方法解析,最后把解析后的字符串转化回去
from requests_toolbelt.multipart.encoder import MultipartEncoder
from my_compat import MultipartEncoder
import urllib
import requests
import json encoded_name = urllib.quote(file_name.encode('utf-8'))//取巧做法,先转化字符
with open(res_path, 'rb') as f_:
m = MultipartEncoder(
fields={'file': (encoded_name, f_,
'application/octet-stream')}
) decoded_m = m.to_string()//解析时不支持中文
decoded_m = decoded_m.replace(encoded_name, file_name)//替代转化
response = requests.post(url,
data=decoded_m,
headers={'Content-Type': m.content_type,
'charset': 'UTF-8'},
verify=False) try:
content = json.loads(response.content)
except ValueError:
content = response.content
return content, response.status_code
后来发现这样做其实很不方便,所以我就阅读MultipartEncoder的源码,发现content_type其实就是一个很简单的随机字符串的构造,而数据的字符流只要符合一定规范就可以构造,再结合requests包,写出了如下的代码,
#coding=utf8
import requests
from uuid import uuid4
import os file_name='test'
url= boundary=uuid4().hex
header={'Content-Type': 'multipart/form-data; boundary={0}'.format(boundary),'charset': 'UTF-8'}
with open(r'C:\test'.decode('utf8'), 'r') as f:
content=f.readlines()
print content
content=''.join(content)
datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}{3}{1}--{0}--{1}'. \
format(boundary,os.linesep, file_name, content,boundary)
print repr(datas)
print header
response = requests.post(url,
data=datas,
headers=header,
verify=False)
print response.status_code,response.text
在windows上调试可以,但在linux上调试一直报错,后来把os.linesep换成指定的'\r\n'分隔符就可以成功了,不知道是我们公司服务器设置问题还是这个库的解析问题。
#coding=utf8
import requests
from uuid import uuid4
import os file_name='test'
url= boundary=uuid4().hex
header={'Content-Type': 'multipart/form-data; boundary={0}'.format(boundary),'charset': 'UTF-8'}
with open(r'C:\test'.decode('utf8'), 'r') as f:
content=f.readlines()
print content
content=''.join(content)
datas = '--{0}{1}Content-Disposition: form-data; name="file"; filename="{2}"{1}Content-Type: application/octet-stream{1}{1}{3}{1}--{0}--{1}'. \
format(boundary,'\r\n', file_name, content,boundary)
print repr(datas)
print header
response = requests.post(url,
data=datas,
headers=header,
verify=False)
print response.status_code,response.text
结合saltstack,在proxy上执行的 "salt '{}' cp.push {}".format(path, agent_id, file_path)命令,效果更佳
解决python发送multipart/form-data请求上传文件的问题的更多相关文章
- python中使用multipart/form-data请求上传文件
最近测试的接口是上传文件的接口,上传单个文件,我主要使用了2种方法~ 接口例如: URL: http://www.baidu.com/*** method:post 参数: { "salar ...
- 巨蟒python全栈开发django11:ajax&&form表单上传文件contentType
回顾: 什么是异步? 可以开出一个线程,我发出请求,不用等待返回,可以做其他事情. 什么是同步? 同步就是,我发送出了一个请求,需要等待返回给我信息,我才可以操作其他事情. 局部刷新是什么? 通过jq ...
- SpringMVC实现PUT请求上传文件
在JQuery中,我们可以进行REST ful中delete和put的请求,但是在java EE标准中,默认只有在POST请求的时候,servlet 才会通过getparameter()方法取得请求体 ...
- Postman Post请求上传文件
Postman Post请求上传文件一.选择post请求方式,输入请求地址 二.填写Headers Key:Content-Type :Value:multipart/form-data 如下图 三. ...
- django 基于form表单上传文件和基于ajax上传文件
一.基于form表单上传文件 1.html里是有一个input type="file" 和 ‘submit’的标签 2.vies.py def fileupload(request ...
- SSM框架下,使用ajax请求上传文件(doc\docx\excel\图片等)
1.准备工作 1.1.添加上传必要jar包 <dependency> <groupId>commons-io</groupId> <artifactId> ...
- vue form表单上传文件
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js">< ...
- JsonResponse类的使用、form表单上传文件补充、CBV和FBV、HTML的模板语法之传值与过滤器
昨日内容回顾 Django请求生命周期 # 1.浏览器发起请求 到达Django的socket服务端(web服务网关接口) 01 wsgiref 02 uwsgi + nginx 03 WSGI协议 ...
- Python3+Selenium3+webdriver学习笔记9(发送富文本信息及上传文件处理)
#!/usr/bin/env python# -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记9(发送富文本信息及上传文件处理)'''from seleni ...
- 使用form表单上传文件
在使用form表单上传文件时候,input[type='file']是必然会用的,其中有一些小坑需要避免. 1.form的 enctype="multipart/form-data" ...
随机推荐
- Shell编程(四)Shell变量
1. 自定义变量(仅在当前shell生效) 1.1 定义变量 #!/usr/bin/bash ip=115.239.210.27 if ping -c1 $ip &>/dev/null ...
- Golang入门教程(十)内建函数
比较常用的内建函数 参考: http://blog.csdn.net/liumiaocn/article/details/54804074
- Spark源码解析 - Spark-shell浅析
1.准备工作 1.1 安装spark,并配置spark-env.sh 使用spark-shell前需要安装spark,详情可以参考http://www.cnblogs.com/swordfall/p/ ...
- 056、macvlan网络结构分析(2019-03-25 周一)
参考https://www.cnblogs.com/CloudMan6/p/7383919.html macvlan不依赖linux bridge brctl show 可以确认没有创建新的b ...
- ImageView获取宽高
在Android里放置一个ImageView im1,宽和高都是200.以下代码都是直接在OnCreate里使用. 1.在Android OnCreate里如果直接使用iv.GetWidth()返回值 ...
- 苹果手机上点击WEUI日期控件不容易点中
主要问题是WEUI cells有Padding,而苹果手机一般屏幕较小,容易点不中导致的 <div class='weui_cell' style="padding-bottom:0p ...
- 堆栈Stack介绍
堆栈(Stack)代表了一个后进先出的对象集合.当您需要对各项进行后进先出的访问时,则使用堆栈.当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素. Stack 类的方法和属性 ...
- Maven 那点事儿(转)
0. 前言 Jason Van Zyl,在 Java 十大风云人物排行榜上或许会看到他. 这兄弟是干嘛的? 他就是 Maven 的创始人,人们都尊称他为“Maven 他爸”. 毋庸置疑,Jason 也 ...
- python笔记---数据基础类型
s = 'laonanHai' s1 = s.capitalize() #首字母大写,其他字母小写 s2 = s.upper() #全部大写 s3 = s.lower() #全部小写 print(s, ...
- 使用C++ stringstream来进行数据类型转换
参考链接: http://blog.csdn.net/tao_627/article/details/39000779