服务器接收文件时,有时会使用表单接收的方式,这意味着我们需要使用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. 网络编程基础【day10】:我是一个进程(三)

    本节内容 1.引子 2.进程的诞生 3.线程 4.争吵 一.引子 我听说我的祖先们生活在专用计算机里, 一生只帮助人类做一件事情,比说微积分运算 了.人口统计了 .生成密码.甚至通过织布机印花 !   ...

  2. spring整合curator实现分布式锁

    为什么要有分布式锁? 比如说,我们要下单,分为两个操作,下单成功(订单服务),扣减库存(商品服务).如果没有锁的话,同时两个请求进来.先检查有没有库存,一看都有,然后下订单,减库存.这时候肯定会出现错 ...

  3. Kafka技术内幕 读书笔记之(五) 协调者——消费者加入消费组

    消费者客户端轮询的3个步骤:发送拉取请求,客户端轮询,获取拉取结果 . 消费者在发送拉取请求之前,必须首先满足下面的两个条件.- 确保消费者已经连接协调者, 即找到服务端中管理这个消费者的协调者节点 ...

  4. CM记录-部署cdh5.3.3集群

    1.安装操作系统,保证联网环境,本文以CentOS 6.8为操作系统(略) 2.wget下载安装包(以5.3.3为例) #mkdir /usr/cdh ---新建cm安装目录 #cd /usr/cdh ...

  5. STM32学习笔记:【001】时钟树与RCC

    导言 如果学过单片机的同学应该不会陌生,学习51单片机时最经常听到的就是“最小系统”. 最小系统里面少不了晶振,否则单片机无法工作. 单片机需要晶振(时钟源)来工作,那么对于STM32芯片同样如此. ...

  6. ACM-ICPC 2018 焦作赛区网络预赛 I Save the Room(水题)

    https://nanti.jisuanke.com/t/31718 题意 问能否用1*1*2的长方体填满a*b*c的长方体. 分析 签到.如果a.b.c都是奇数,一定不能. #include< ...

  7. c# 三种传参方式 in,out,ref

    in:默认方式,传值不返回 out:不传值 但是会返回新值给予传参对象 ref:传存储地址,所以传参前必须赋值初始化,传值后的运算结果直接作用在传参上 Out和ref的效果差不多

  8. oldboy s21day01

    1.操作系统的作用? 人操作软件,软件控制操作系统,操作系统控制硬件.2.列举你听过的操作系统及区别? 1.Windows 7/8/10 付费,操作方便,长时间运行卡顿. 2.Linux(Ubuntu ...

  9. Android几个比较有用的插件

    1.Android  Drawable Importer 2.Android ButterKnife Zelezny 使用方法,在SetContentView上右键,Generate 3.Androi ...

  10. Image转Base64

    今天和一个朋友联调图片转Base64时发现一个问题 public static string ImageToBase64(Image img) { BinaryFormatter binFormatt ...