服务器接收文件时,有时会使用表单接收的方式,这意味着我们需要使用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请求上传文件的问题的更多相关文章

  1. python中使用multipart/form-data请求上传文件

    最近测试的接口是上传文件的接口,上传单个文件,我主要使用了2种方法~ 接口例如: URL: http://www.baidu.com/*** method:post 参数: { "salar ...

  2. 巨蟒python全栈开发django11:ajax&&form表单上传文件contentType

    回顾: 什么是异步? 可以开出一个线程,我发出请求,不用等待返回,可以做其他事情. 什么是同步? 同步就是,我发送出了一个请求,需要等待返回给我信息,我才可以操作其他事情. 局部刷新是什么? 通过jq ...

  3. SpringMVC实现PUT请求上传文件

    在JQuery中,我们可以进行REST ful中delete和put的请求,但是在java EE标准中,默认只有在POST请求的时候,servlet 才会通过getparameter()方法取得请求体 ...

  4. Postman Post请求上传文件

    Postman Post请求上传文件一.选择post请求方式,输入请求地址 二.填写Headers Key:Content-Type :Value:multipart/form-data 如下图 三. ...

  5. django 基于form表单上传文件和基于ajax上传文件

    一.基于form表单上传文件 1.html里是有一个input type="file" 和 ‘submit’的标签 2.vies.py def fileupload(request ...

  6. SSM框架下,使用ajax请求上传文件(doc\docx\excel\图片等)

    1.准备工作 1.1.添加上传必要jar包 <dependency> <groupId>commons-io</groupId> <artifactId> ...

  7. vue form表单上传文件

    <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js">< ...

  8. JsonResponse类的使用、form表单上传文件补充、CBV和FBV、HTML的模板语法之传值与过滤器

    昨日内容回顾 Django请求生命周期 # 1.浏览器发起请求 到达Django的socket服务端(web服务网关接口) 01 wsgiref 02 uwsgi + nginx 03 WSGI协议 ...

  9. Python3+Selenium3+webdriver学习笔记9(发送富文本信息及上传文件处理)

    #!/usr/bin/env python# -*- coding:utf-8 -*-'''Selenium3+webdriver学习笔记9(发送富文本信息及上传文件处理)'''from seleni ...

  10. 使用form表单上传文件

    在使用form表单上传文件时候,input[type='file']是必然会用的,其中有一些小坑需要避免. 1.form的 enctype="multipart/form-data" ...

随机推荐

  1. Shell编程(四)Shell变量

    1. 自定义变量(仅在当前shell生效) 1.1 定义变量 #!/usr/bin/bash ip=115.239.210.27 if ping -c1 $ip &>/dev/null ...

  2. Golang入门教程(十)内建函数

    比较常用的内建函数 参考: http://blog.csdn.net/liumiaocn/article/details/54804074

  3. Spark源码解析 - Spark-shell浅析

    1.准备工作 1.1 安装spark,并配置spark-env.sh 使用spark-shell前需要安装spark,详情可以参考http://www.cnblogs.com/swordfall/p/ ...

  4. 056、macvlan网络结构分析(2019-03-25 周一)

    参考https://www.cnblogs.com/CloudMan6/p/7383919.html   macvlan不依赖linux bridge   brctl show 可以确认没有创建新的b ...

  5. ImageView获取宽高

    在Android里放置一个ImageView im1,宽和高都是200.以下代码都是直接在OnCreate里使用. 1.在Android OnCreate里如果直接使用iv.GetWidth()返回值 ...

  6. 苹果手机上点击WEUI日期控件不容易点中

    主要问题是WEUI cells有Padding,而苹果手机一般屏幕较小,容易点不中导致的 <div class='weui_cell' style="padding-bottom:0p ...

  7. 堆栈Stack介绍

    堆栈(Stack)代表了一个后进先出的对象集合.当您需要对各项进行后进先出的访问时,则使用堆栈.当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素. Stack 类的方法和属性 ...

  8. Maven 那点事儿(转)

    0. 前言 Jason Van Zyl,在 Java 十大风云人物排行榜上或许会看到他. 这兄弟是干嘛的? 他就是 Maven 的创始人,人们都尊称他为“Maven 他爸”. 毋庸置疑,Jason 也 ...

  9. python笔记---数据基础类型

    s = 'laonanHai' s1 = s.capitalize() #首字母大写,其他字母小写 s2 = s.upper() #全部大写 s3 = s.lower() #全部小写 print(s, ...

  10. 使用C++ stringstream来进行数据类型转换

    参考链接: http://blog.csdn.net/tao_627/article/details/39000779