本文主要给大家介绍的是关于利用python模拟实现POST请求提交图片的方法,分享出来供大家参考学习,下面来一看看详细的介绍:

使用requests来模拟HTTP请求本来是一件非常轻松的事情,比如上传图片来说,简单的几行代码即可:

import requests

files = {'attachment_file': ('1.png', open('1.png', 'rb'), 'image/png', {})}

values = {'next':"http://www.xxxx.com/xxxx"}

r = requests.post('http://www.xxxx.com/upload', files=files, data=values) # 成功

r = requests.post('http://www.xxxx.com/upload', files=files, data=values) # 失败

r = requests.post('http://www.xxxx.com/upload', files=files, data=values) # 失败

r = requests.post('http://www.xxxx.com/upload', files=files, data=values) # 失败

r = requests.post('http://www.xxxx.com/upload', files=files, data=values) # 失败

...

不过我今天在调试一个django程序的时候却遇到了大坑————为了偷懒,我直接在ipython中执行了上述代码,第一次提交的时候一切正常,但第二次之后提交就怎么也通过不了django的form验证。

验证部分的代码很简单:

......

form = AttachmentForm(request.POST, request.FILES)

if form.is_valid():

form.save(request, obj)

messages.success(request,_('Your attachment was uploaded.'))

return HttpResponseRedirect(next)

......

什么鬼!?怎么只有第一次成功提交???后面全失败??只好一步一步的跟进到django源码中,发现问题出在django/forms/fields.py文件中:

def to_python(self, data):

if data in validators.EMPTY_VALUES:

return None

# UploadedFile objects should have name and size attributes.

try:

file_name = data.name

file_size = data.size

except AttributeError:

raise ValidationError(self.error_messages['invalid'])

if self.max_length is not None and len(file_name) > self.max_length:

error_values = {'max': self.max_length, 'length': len(file_name)}

raise ValidationError(self.error_messages['max_length'] % error_values)

if not file_name:

raise ValidationError(self.error_messages['invalid'])

if not self.allow_empty_file and not file_size:

raise ValidationError(self.error_messages['empty'])

return data

在第一次执行的时候,一切正常,这个data即InMemoryUploadFile文件类型,name、size就是我们上传的图片名、大小,而第二次执行post请求时候,发现data.size居然变成了0?!怪不得直接引发了if not self.allow_empty_file and not file_size这个判断的异常呢!

由此可知,问题的核心并不出现在django对于表单验证的部分,而是出自发送请求的部分。不过发请求的部分代码很简单啊?分别输出了正常情况和错误情况requests发出的请求包,发现区别了:

#正常情况

In [28]: r = requests.post('http://www.xxxx.com/upload', files=files, data=values)

In [29]: r.request.body

#错误情况

In [33]: r = requests.post('http://www.xxxx.com/upload', files=files, data=values)

In [34]: r.request.body

Out[34]: '--155322d3e780432bb06e58135e041c8f\r\nContent-Disposition: form-data; name="next"\r\n\r\nhttp://www.xxxx.com/upload\r\n--155322d3e780432bb06e58135e041c8f\r\nContent-Disposition: form-data; name="attachment_file"; filename="1.png"\r\nContent-Type: image/png\r\n\r\n\r\n--155322d3e780432bb06e58135e041c8f--\r\n'

正常情况没输出,错误情况反而看着像正常情况下的输出?这不科学啊?

结合以上2点,我隐约感觉问题出在数据的构造上,关键在于files = {'attachment_file': ('1.png', open('1.png', 'rb') , 'image/png', {})}这里,首先关于字典、列表这种可变类型作为函数的参数传递时候就需要特别注意,其次open函数打开了一个文件,那么哪里关闭文件了呢?

带着这个怀疑,我把代码改写成:

fl = open('1.png','rb')

files = {'attachment_file': ('1.png', fl, 'image/png', {})}

r1 = requests.post('http://www.xxxx.com/upload', files=files, data=values)

fl.close()

fl = open('1.png','rb')

files = {'attachment_file': ('1.png', fl, 'image/png', {})}

r2 = requests.post('http://www.xxxx.com/upload', files=files, data=values)

然后再执行,果然成功上传了2张图片。其实按照正常情况不会出现测试时候这种打开一张图片不停上传的情形,不过也正因为这样才会遇到如此有意思的问题。关于requests中files对象的处理代码在models.py文件中,有兴趣的读者可以自行调试。

另外,requests调用时上传文件名中不能包含中文,否则也不能通过django表单验证,这里也不深究原因了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

python post请求 上传图片_利用python模拟实现POST请求提交图片的方法相关推荐

  1. python实现自动上传图片_利用python脚本实现使用typora编写markdown时图片自动上传到chevereto图床...

    复制粘贴以下代码 #!/usr/bin/env python3 # -*- encoding: utf-8 -*- # author: guiu # data: 2020.2.28 import re ...

  2. 使用python进行渗透测试_利用Python进行Web渗透测试(五):剖析HTTP请求

    本篇概要URL的结构 HTTP头域 HTTP状态码 一个完整的HTTPget请求 在上一篇我们简单介绍了HTTP协议的概念和知识,本篇我们来详细剖析一下HTTP的请求,将这两篇综合起来,我们就对HTT ...

  3. 利用python进行数据分析 笔记_利用python进行数据分析--(阅读笔记一)

    原博文 2016-06-17 23:21 − 以此记录阅读和学习<利用Python进行数据分析>这本书中的觉得重要的点! 第一章:准备工作 1.一组新闻文章可以被处理为一张词频表,这张词频 ...

  4. python ks值计算_利用Python计算KS的实例详解

    在金融领域中,我们的y值和预测得到的违约概率刚好是两个分布未知的两个分布.好的信用风控模型一般从准确性.稳定性和可解释性来评估模型.sOf免费资源网 一般来说.好人样本的分布同坏人样本的分布应该是有很 ...

  5. python实现邮件客户端_利用python实现简单的邮件发送客户端示例

    脚本过于简单,供学习和参考.主要了解一下smtplib库的使用和超时机制的实现.使用signal.alarm实现超时机制. #!/usr/bin/env python # -*- coding: ut ...

  6. python制作图片墙_利用python生成照片墙的示例代码

    PIL(Python Image Library)是python的第三方图像处理库,但是由于其强大的功能与众多的使用人数,几乎已经被认为是python官方图像处理库了.其官方主页为:PIL. PIL历 ...

  7. python连接opencv库_利用Python和OpenCV库将URL转换为OpenCV格式的方法

    今天的博客是直接来源于我自己的个人工具函数库. 过去几个月,有些PyImageSearch读者电邮问我:"如何获取URL指向的图片并将其转换成OpenCV格式(不用将其写入磁盘再读回)&qu ...

  8. python京东自动签到_利用python Selenium实现自动登陆京东签到领金币功能

    如何自动登陆京东? 我们先来看一下京东的登陆页面,如下图所示: [插入图片,登陆页面] 登陆框就是右面这一个框框了,但是目前我们遇到一个困呐,默认的登陆方式是扫码登陆,如果我们想要以用户民个.密码的形 ...

  9. python powerbi知乎_利用Python调用Power BI REST API

    本文是D-BI之Power BI REST API系列第三篇,讲解如何利用一段简单的Python脚本实现Power BI REST API的调用,将使用与上文完全不同的方法 前述 上文<Powe ...

最新文章

  1. MyEclipse8.5注册码 到2015年
  2. keil 多文件组织方法
  3. boost::filesystem::equivalent的用法测试程序
  4. BIOS INT 10-13功能调用的“另类”玩法
  5. php session mysql_php session mysql存储
  6. 虚拟服务器容器,docker容器和虚拟机的区别
  7. Linux下做一个arp欺骗程序6,LINUX下防ARP欺骗攻击
  8. 160 - 6 aLoNg3x.1
  9. Linux内核配置系统浅析
  10. Java第二次作业第一题
  11. 使用双向链表构建二叉树_python:26.二叉搜索树与双向链表
  12. Nginx服务器开启gzip压缩功能额必要性
  13. 玛森:Python爬虫书籍推荐
  14. Photoshop实例视频教程
  15. CSS 的相对单位 em 与 ex
  16. IRC下载TLF0day资源
  17. 口模块型3500/22-01-01-00
  18. android inflate 方法,Android LayoutInflater中 Inflate()方法应用
  19. loadRunner之使用谷歌浏览器录制脚本
  20. windows系统在路由器组成的局域网中共享打印机

热门文章

  1. eclipse启动报JVM terminated. Exit code=-1的解决方法
  2. Invalid byte tag in constant pool: 19 与 javax/el/ELManager问题解决
  3. 无法启动MYSQL服务”1067 进程意外终止”解决的方法
  4. vue开发环境和生产环境里面解决跨域的几种方法
  5. Math.Pow()是如何在.NET Framework中实现的?
  6. 如何从Android中的另一个应用程序启动活动
  7. .gitignore for Visual Studio项目和解决方案
  8. SpringBoot数据缓存
  9. js数组中forEach/some/every/map/filter/reduce的区别
  10. Object.keys()