使用python向服务器POST大文件

使用python向服务器POST大文件

python 对http操作有几个库 urllib 、 urllib2 还有httplib

httplib比较偏底层 一般情况下使用urllib和urllib2就行了

NOTICE

在python3中urllib与urllib2被分割合并为了 urllib.request, urllib.parse, and urllib.error

httplib重命名为 http.client

分析http协议

python的这几个库中并没有提供直接上传文件的接口 我们先看下普通浏览器是怎么上传文件的 这里我在本地创建简单php程序 若有提交文件,则打印出文件相关的信息。否则显示一个上传表单表单

这里推荐一个抓包工具fildder 可以很方便的抓取htttp数据,并且直观的显示

下面就是抓取到的内容

从第1-13行就是请求消息http头部的内容,然后下面有个空行 比较重要的几行是

请求消息(Request message)有以下几部分组成

  • 请求行(request line), 例如 GET /images/logo.png HTTP/1.1
  • 请求头(Request Headers) 比如上面的 Host: localhost、 Content-Length: 295
  • 空行
  • 消息主体 message body

NOTICE

请求行与请求头必须以结尾,空行只能有不能有空格什么的 在HTTP/1.1协议中,除了Host 所有的请求头都是可选的(当然若上传文件的话,就必须设置了Content-Length和Content-Type了, 不然服务器收不到数据的,虽然也能成功响应)

这里message body的类型是multipart/form-data;

boundary 是随机的内容每次请求都不一样, Content-Type为 multipart/form-data; 可同时传输多项数据,而这些数据就是通过 boundary分割开来的

每一项的数据都是’–‘+boundary+换行开始 ,然后是Content-Disposition: form-data;name=”表单项名”

若是文件的话 还有个filename 以及Content-Type,接下来一个空行

最后’–‘+boundary+’–‘+换行结束

到这里整个http请求就结束了

模拟提交数据

其实http协议就是字符串按照约定规则拼接到一起 然后服务器再来解析得到数据 所以我们自己直接使用socket也能发起了一个http请求

但是有了urllib2我们可以省很多事 只需“拼接”内容部分就行了

url 可以是一个链接或者Request对象 data 就是我们要“拼接的内容”

下面是运行后的输出结果

php能正常接收传输的文件了 但是这里有个问题 ,我们拼接数据的时候使用的是

直接把文件内容读到内存中去了,小文件还好,要是几百M上G的文件还用这种方法就不行了,这样会把你的内存吃干。

所以我们就需要弄个变通的方法,让它一块一块的发送数据,读一点发送一点。 这几个库并没有提供类似的方法实现这一个功能,所以就需要自己动手了。

首先介绍一个python的关键字 yield 关于介绍python yield的文章可以查看Python yield 使用浅析 可以通过它来实现一个生成器(generator) 来不断的读取文件数据,而且是只在我们需要的时候读取

然后我重写了 httplib 中 HTTPConnection.send(data)使它可以接收一个generator,从里面取数据然后发送 下面是原版HTTPConnection.send的源码

它支持文件类型File Object 或者是一个字符串

下面是个重新版本

当然若想实现完美的文件提交,还需要做个封装,下面是一个简单的实现,还有写不完善的地方,post数据只能传文件,打算做个python lib封装一下

现在有很多现成的第三方库比如 poster Requests 可以实现这些功能了,但是由于是第三方库需要用户手动安装,在一个我需要上传大文件时有个回调功能,这样就能显示进度了。 等运行稳定了会添加到kuaipan cli 里面,就可以摆脱poster依赖

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是两种Python文件服务器的实现方式: 1. 使用Python 2.x自带的SimpleHTTPServer模块实现简单文件下载和上传服务: - 在命令行中进入需要共享文件的目录,执行以下命令即可启动文件下载服务: ```shell python -m SimpleServer 8081 ``` 这将在本地8081端口启动一个简单的文件下载服务,可以通过浏览器访问http://localhost:8081来下载共享的文件。 - 如果需要启动带上传功能的文件服务,可以使用SimpleHTTPServerWithUpload.py脚本,该脚本需要先下载并保存到需要共享文件的目录下,然后执行以下命令即可启动文件上传和下载服务: ```shell python SimpleHTTPServerWithUpload.py 8089 ``` 这将在本地8089端口启动一个带上传和下载功能的文件服务,可以通过浏览器访问http://localhost:8089来上传和下载共享的文件。 2. 使用Python Flask框架实现带认证功能的文件服务器: - 首先需要安装Flask框架,可以使用以下命令进行安装: ```shell pip install flask ``` - 然后可以使用以下代码实现带认证功能的文件服务器: ```python from flask import Flask, request, send_from_directory from werkzeug.utils import secure_filename import os app = Flask(__name__) app.config['UPLOAD_FOLDER'] = 'uploads' app.config['DOWNLOAD_FOLDER'] = 'downloads' app.config['ALLOWED_EXTENSIONS'] = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'} app.config['USERNAME'] = 'admin' app.config['PASSWORD'] = 'password' def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS'] @app.route('/uploads', methods=['POST']) def upload_file(): if request.method == 'POST': username = request.authorization.username password = request.authorization.password if username != app.config['USERNAME'] or password != app.config['PASSWORD']: return 'Unauthorized', 401 file = request.files['file'] if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) return 'File uploaded successfully' else: return 'Invalid file type', 400 @app.route('/downloads/<filename>', methods=['GET']) def download_file(filename): username = request.authorization.username password = request.authorization.password if username != app.config['USERNAME'] or password != app.config['PASSWORD']: return 'Unauthorized', 401 return send_from_directory(app.config['DOWNLOAD_FOLDER'], filename) if __name__ == '__main__': app.run(debug=True) ``` 这将在本地启动一个带认证功能的文件服务器,可以通过浏览器访问http://localhost:5000/uploads来上传文件,访问http://localhost:5000/downloads/<filename>来下载文件,其中<filename>是需要下载的文件名。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值