python - 如何在使用带有 request.post 方法的 files 参数上传文件时应用压缩
问题描述
将 Flask 服务器配置为支持压缩:
服务器.py
import os
import json
import tempfile
from flask import Flask, request
from flask_compress import Compress
app = Flask(__name__)
app.config['COMPRESS_MIMETYPES'] = set(['text/html', 'text/css', 'text/xml', 'application/json', 'application/javascript'])
app.config['COMPRESS_LEVEL'] = 6
app.config['COMPRESS_MIN_SIZE'] = 500
Compress(app)
@app.route('/', methods=['GET', 'POST'])
def index():
print('get_json: %s get_data: %s' % (type(request.get_json()), type(request.get_data())) )
for key, value in request.files.items():
if value.content_type == 'application/json':
data = json.loads(value.stream.read())
print('got json data %s' % data)
elif value.content_type == 'application/octet-stream':
dst_filepath = os.path.join(tempfile.mktemp(), value.filename)
if not os.path.exists(os.path.dirname(dst_filepath)):
os.makedirs(os.path.dirname(dst_filepath))
with open(dst_filepath, 'wb') as fd:
for chunk in value:
fd.write(chunk)
print('saved file as %s' % dst_filepath)
return 'OK', 200
app.run('0.0.0.0', 80)
client.py
发送request
带有 json 字典和文件数据的单曲。
客户端.py
import requests
import json
import os
payload = {"param_1": "value_1", "param_2": "value_2"}
filepath = '/file/path/to/local_file.zip'
data = {'json': ('some-json', json.dumps(payload), 'application/json'),
'file': (os.path.basename(filepath), open(filepath, 'rb'), 'application/octet-stream')}
response = requests.post('http://127.0.0.1:80/', files = data)
为了尽量减少上传时间,我想发送压缩文件数据(连同 json 数据)的请求。如何实现?
后来编辑:
看起来有一个方法headers
参数request.post()
可用于指定编码类型。
response = requests.post('http://127.0.0.1:80/',
files = data,
headers = {'Accept-Encoding': 'gzip'})
但是我们如何压缩data
用于存储文件数据的字典和 json 字典呢?
解决方案
该解决方案使用gzip
模块在客户端发送文件时压缩文件的二进制数据,并在服务器接收到发送的压缩文件数据时解压缩。
服务器.py
#!/usr/bin/env python
import os
import io
import json
import gzip
import hashlib
import tempfile
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
print('get_json: %s get_data: %s' % (type(request.get_json()), type(request.get_data())) )
for key, file_storage in request.files.items():
if file_storage.content_type == 'application/json':
data = json.loads(file_storage.stream.read())
print('got json data %s' % data)
elif file_storage.content_type == 'application/octet-stream':
zip_str = ''.join([chunk for chunk in file_storage])
zip_str_md5_hash = hashlib.md5(zip_str).hexdigest()
zip_filepath = os.path.join(tempfile.mktemp(), file_storage.filename)
if not os.path.exists(os.path.dirname(zip_filepath)):
os.makedirs(os.path.dirname(zip_filepath))
with open(zip_filepath, 'wb') as fd:
for chunk in zip_str:
fd.write(chunk)
filepath = zip_filepath.replace('.zip', '')
zip_str_file = gzip.GzipFile(fileobj=io.BytesIO(zip_str))
with open(filepath, 'wb') as fd:
for chunk in zip_str_file.read():
fd.write(chunk)
print('compressed str as zip_str: %s' % hashlib.md5(zip_str).hexdigest())
print('read compressed data as zip_filepath: %s' % hashlib.md5(open(zip_filepath, 'rb').read()).hexdigest())
print('read uncompressed filepath: %s' % hashlib.md5(open(filepath, 'rb').read()).hexdigest())
print('uncompressed zip_str as zip_str_file: %s' % hashlib.md5(zip_str_file.read()).hexdigest())
return 'OK', 200
app.run('0.0.0.0', 80)
客户端.py
import requests
import json
import os
import gzip
import io
import hashlib
payload = {"param_1": "value_1", "param_2": "value_2"}
filepath = '/file/path/to/local_file.zip'
bytes_io = io.BytesIO()
gzip_file = gzip.GzipFile(fileobj=bytes_io, mode='w')
open_file = open(filepath, 'rb')
gzip_file.write(bytes(open_file.read()))
gzip_file.close()
zip_str = bytes_io.getvalue()
data = {'json': ('some-json', json.dumps(payload), 'application/json'),
'file': ('%s.zip'%os.path.basename(filepath), zip_str, 'application/octet-stream')}
response = requests.post('http://127.0.0.1:80', files = data)
print('file open read data as filepath %s' % hashlib.md5(open(filepath, 'rb').read()).hexdigest())
print('bytes_io%s' % hashlib.md5(bytes_io.getvalue()).hexdigest())
print('compressed str as zip_str %s' % hashlib.md5(zip_str).hexdigest())
推荐阅读
- php - (API) Laravel 7 上不允许使用 tymon/jwt-auth 的 405 方法
- javascript - ReactJS - 如何在子组件内部获取由父组件传递的道具的详细信息?
- python-3.x - 通过 Python3.7 连接到 SQL Server 的操作错误
- python - 在一个数字序列中找到最大的 n 位乘积
- delphi - Delphi 计算 TPopupMenu 大小
- azure - Azure - GCP - 通过 Openvpn 连接
- batch-file - 任务自动启动时任务调度器权限不足
- orbeon - 登录后,显示 HTTP 状态 403
- json - 如何从 Angular 添加或编辑客户端 json 文件?
- node.js - AWS-EB 错误:找不到模块“快递”