python - 如何手动处理上传的文件数据?
问题描述
我正在尝试手动保存上传的文件以供学习,没有request.files
.
我正在使用 Flask,它给了我一种str
原始身体数据,通过print(type(reqeust.data))
- 我有点迷惑不解了。我不应该得到二进制数据
<type bytes>
吗?
但后来我又想,即使我得到二进制数据,我怎样才能过滤前几行,然后从正确的地方开始读取二进制数据呢?
例如:
-----------------------------1699415032232102060211780227
Content-Disposition: form-data; name="myfile"; filename="Screenshot from 2018-10-05 15-49-07.png"
Content-Type: image/png
�PNG
�ߧd�tEXtSoftwaregnome-screenshot��>�IDATx���OPY����l�*c���=��El"f[��)3��S�+z-v�0�c������zp����6��qS�\W��6S�qM�S=tG�Ǩb��A�ؒvc���@rh��.N]���?JK����b+�J��(�����OR�T
-----------------------------1699415032232102060211780227--
- 有人可以教我如何手动保存文件数据吗?
解决方案
最后我自己想通了。
我从中得到的原因
str
是request.data
因为我使用的是python2.7
烧瓶包。真是让人头疼。virtualenv
下次我肯定会使用,即使是用于测试。但是我仍然不明白为什么我可以在服务器代码中使用python3语法而包与python2.7相关。所以实际上我正在获取原始字节数据,例如
b'raw binary data'
fromrequest.data
。并且来自其他功能的数据,例如request.form['firstname']
已经解码。
所以现在问题归结为我如何重建文件,提供二进制数据。
首先,我准备了 2 个小文件进行测试。
文件1:1.txt
内容:1234567
内容(使用open('test.png', 'rb').read()
):
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\x08\x08\x02\x00\x00\x00\xa4\xafB\xe2\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00\x10tEXtSoftware\x00Shutterc\x82\xd0\t\x00\x00\x00\x15IDAT\x08\xd7c\xd4\xe5Tb\xc0\x01\x98\x18p\x83\xa1"\x07\x00T;\x00h\xb9\x9335\x00\x00\x00\x00IEND\xaeB`\x82'
所以request.data
我在服务器上看到的是:
b'-----------------------------16866548741414816351605255076\r\nContent-Disposition: form-data; name="myfile"; filename="1.txt"\r\nContent-Type: text/plain\r\n\r\n1234567\r\n-----------------------------16866548741414816351605255076\r\nContent-Disposition: form-data; name="myfile2"; filename="test.png"\r\nContent-Type: image/png\r\n\r\n\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\x08\x08\x02\x00\x00\x00\xa4\xafB\xe2\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00\x10tEXtSoftware\x00Shutterc\x82\xd0\t\x00\x00\x00\x15IDAT\x08\xd7c\xd4\xe5Tb\xc0\x01\x98\x18p\x83\xa1"\x07\x00T;\x00h\xb9\x9335\x00\x00\x00\x00IEND\xaeB`\x82\r\n-----------------------------16866548741414816351605255076--\r\n'
稍微格式化一下:
(数据不能直接使用,因为我添加了额外的新行来显示。)
b'-----------------------------16866548741414816351605255076\r\n
Content-Disposition: form-data; name="myfile"; filename="1.txt"\r\n
Content-Type: text/plain\r\n\r\n
1234567\r\n
-----------------------------16866548741414816351605255076\r\n
Content-Disposition: form-data; name="myfile2"; filename="test.png"\r\n
Content-Type: image/png\r\n\r\n
\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\x08\x08\x02\x00\x00\x00\xa4\xafB\xe2\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00\x10tEXtSoftware\x00Shutterc\x82\xd0\t\x00\x00\x00\x15IDAT\x08\xd7c\xd4\xe5Tb\xc0\x01\x98\x18p\x83\xa1"\x07\x00T;\x00h\xb9\x9335\x00\x00\x00\x00IEND\xaeB`\x82\r\n
-----------------------------16866548741414816351605255076--\r\n'
让raw_data = binary data above
files_data_array = raw_data.split(b'-----------------------------16866548741414816351605255076\r\n)
然后我得到一个数组,每个文件都在不同的索引中。
这里files_data_array[1]
包含第一个文件元信息和数据。files_data_array[2]
包含第二个文件元信息和数据。如果您有更多文件,依此类推。
[b'', b'Content-Disposition: form-data; name="myfile"; filename="1.txt"\r\nContent-Type: text/plain\r\n\r\n1234567\r\n', b'Content-Disposition: form-data; name="myfile2"; filename="test.png"\r\nContent-Type: image/png\r\n\r\n\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\x08\x08\x02\x00\x00\x00\xa4\xafB\xe2\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00\x10tEXtSoftware\x00Shutterc\x82\xd0\t\x00\x00\x00\x15IDAT\x08\xd7c\xd4\xe5Tb\xc0\x01\x98\x18p\x83\xa1"\x07\x00T;\x00h\xb9\x9335\x00\x00\x00\x00IEND\xaeB`\x82\r\n-----------------------------16866548741414816351605255076--\r\n']
file2_data = files_data_array[2]
b'Content-Disposition: form-data; name="myfile2"; filename="test.png"\r\nContent-Type: image/png\r\n\r\n\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\x08\x08\x02\x00\x00\x00\xa4\xafB\xe2\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00\x10tEXtSoftware\x00Shutterc\x82\xd0\t\x00\x00\x00\x15IDAT\x08\xd7c\xd4\xe5Tb\xc0\x01\x98\x18p\x83\xa1"\x07\x00T;\x00h\xb9\x9335\x00\x00\x00\x00IEND\xaeB`\x82\r\n-----------------------------16866548741414816351605255076--\r\n'
然后将元数据拆分为file2_meta_info = file2_data.split(b'\r\n\r\n', maxsplit=1)[0]
. 请注意,这里我是拆分二进制数据,如果b'\r\n\r\n'
文件数据中有,maxsplit
则需要设置。
现在我得到file2_meta_info
as b'Content-Disposition: form-data; name="myfile"; filename="1.txt"'
,我可以对其进行解码并获得我想要的任何元信息。
现在转向文件正文数据本身,file2_body_data = file2_data.split(b'\r\n\r\n', maxsplit=1)[1]
我明白了
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\t\x00\x00\x00\x08\x08\x02\x00\x00\x00\xa4\xafB\xe2\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\x00\x00\x10tEXtSoftware\x00Shutterc\x82\xd0\t\x00\x00\x00\x15IDAT\x08\xd7c\xd4\xe5Tb\xc0\x01\x98\x18p\x83\xa1"\x07\x00T;\x00h\xb9\x9335\x00\x00\x00\x00IEND\xaeB`\x82\r\n-----------------------------16866548741414816351605255076--\r\n'
test.png
与开头显示的内容相比,我仍然需要削减一些字节
real_file2_body_data = file2_body_data.rsplit(b'\r\n', maxsplit=2)[0]'
最后,我可以使用以下命令重建文件:
f = open('test2.png', 'wb')
f.write(real_file2_body_data)
f.close()
完毕!
推荐阅读
- regex - 如何在正则表达式中至少一次从集合中无序选择每个元素?
- r - R:ggplot - 根据组绘制具有不同颜色的数据点的趋势线
- c# - ASP.NET Core AuthorizationHandler 未被调用
- python - AWS lambda 调用时不运行代码
- javascript - 未更新使用 JavaScript 的密码确认
- docker - Gitlab 使用 helm 安装分蘖导致 kubernetes-charts.storage.googleapis.com 不是有效的图表存储库
- javascript - displayChoice() 和使用 .innerHTML 有什么区别?
- c# - 如何将对象列表投影到嵌套对象列表中
- css - 使标题内的文本响应
- c# - 如何在另一个pdf,.NET中打印带有可编辑字段的pdf?