Mar*_*man 5 python base64 python-requests
我正在使用requests对文件执行 HTTP PUT,但出于某种原因,它首先上传原始 ASCII 码而不是 base64 编码。
files = {'file': ('mydata.csv', open('mydata.csv', 'rb'))}
...
try:
logging.info("Upload URL: " + insert_upload_url)
headers = {'Content-type': 'multipart/form-data'}
upload_res = requests.put(insert_upload_url, files=files,
data={'insertUpload': data}, headers=headers)
logging.info("Status: " + str(upload_res.status_code))
if upload_res.status_code != requests.codes.ok:
logging.info("Reason: " + upload_res.reason)
else:
logging.info("Response: " + upload_res.text)
except Exception as e:
logging.info("Error: " + e.message)
Run Code Online (Sandbox Code Playgroud)
当我转储原始 HTTP 请求时,我看到数据没有被编码为application/octet-streambase64,也不是 base64:
PUT /apibatchmember/services/rest/batchmemberservice/G9X7CsNn3HisxFdwAu4W76mBewUkQcKD_limGK1MDZ-eW3-olsn8HW0l5oePvEU_ZwHaPbEz2_c1YonjauDs7Jhk9DGvGNSTLMbgSSY9TGVuk00I_-tKPw8mjoXzC63YsFzBIYIeYXHKf34dYxmmhz4iSeDw/batchmember/insertUpload HTTP/1.1
Host: api.example.com
Content-Length: 5062
Content-type: multipart/form-data
Accept-Encoding: gzip, deflate, compress
Accept: */*
User-Agent: python-requests/1.2.3 CPython/2.7.5 Darwin/12.5.0
--5f934d42eabb4d7abe8bdef2cea94b6b
Content-Disposition: form-data; name="insertUpload"
<?xml version="1.0" encoding="UTF-8"?>
<insertUpload>
<criteria>LOWER(EMAIL)</criteria>
<fileName>email.csv</fileName>
<separator>,</separator>
<fileEncoding>UTF-8</fileEncoding>
<skipFirstLine>false</skipFirstLine>
<dateFormat>mm/dd/YYYY</dateFormat>
<mapping>
<column>
<colNum>0</colNum>
<fieldName>CUSTNUM</colNum>
<column>
<column>
<colNum>1</colNum>
<fieldName>FIRSTNAME</colNum>
<column>
<column>
<colNum>2</colNum>
<fieldName>LASTNAME</colNum>
<column>
<column>
<colNum>3</colNum>
<fieldName>EMAIL</colNum>
<column>
</mapping>
</insertUpload>
--5f934d42eabb4d7abe8bdef2cea94b6b
Content-Disposition: form-data; name="file"; filename="email.csv"
Content-Type: text/csv
\xef\xbb\xbf1045,Janice,Waddell,blah@example.com
1156,Scott,Sheldon,blah@example.com
1267,Adrianus,Lengkeek,blah@example.com
1295,EDWIN,ODIFE,blah@example.com
1345,Albert,Stephenson,blah@example.com
...
--5f934d42eabb4d7abe8bdef2cea94b6b--
Run Code Online (Sandbox Code Playgroud)
我怎样才能让那text/csv部分成为 base64 编码的流?
谢谢!
更新
我现在使用以下方法获取正确的附件标题:
with open('/Users/mark.richman/email.csv', 'rb') as fd:
b64data = base64.b64encode(fd.read())
files = {'file': ('email.csv', b64data, 'application/octet-stream')}
Run Code Online (Sandbox Code Playgroud)
然而,我还是不明白 Content-Transfer-Encoding: base64文件附件标题。任何的想法?
更新 2
我不得不这样修改标题: files = {'file': ('email.csv', b64data, 'application/octet-stream\r\nContent-Transfer-Encoding: base64')}
我在 HTTP 转储中看到了标头,但我仍然回来了 HTTP 415 Unsupported Media Type.
更新 3
看起来requests需要一个 API 更新来支持我在这里尝试做的事情。multipart 的第一部分(XML 数据)需要Content-Type: text/xml设置,API 目前不支持。讨论到这里。
你必须做
import base64
response = requests.put(url, data={'insertUpload': base64.b64encode(data)}, files=files, ...)
Run Code Online (Sandbox Code Playgroud)
但您没有定义data,因此如果您尝试使用文件对象,那么这将不起作用。
如果data是一个字符串那么这将工作正常。
我最初误解了你的问题。
因此,如果您不想避免将整个文件加载到内存中(看起来您就是这样),您可以这样做
with open('mydata.csv', 'rb') as fd:
b64data = base64.b64encode(fd.read())
files = {'file': ('mydata.csv', b64data, 'application/octet-stream')}
requests.put(...) # everything here is the same as what you did
Run Code Online (Sandbox Code Playgroud)
另一方面,如果您希望对数据进行编码而不将其完全加载到内存中,那么没有现有的方法可以实现这一点。为了正确地对整个内容进行 Base64 编码,首先需要文件中的所有内容。考虑(例如)以下内容:
print(base64.b64encode('line\n'))
# => bGluZQo=
print(base64.b64encode('line\nline\n'))
# => bGluZQpsaW5lCg==
Run Code Online (Sandbox Code Playgroud)
它们是相关的,但不能简单地连接起来。您可能会更幸运地将手头的问题范围限定为仅使用创建一个类似文件的对象来动态对文本进行 Base64 编码等。祝你好运!
| 归档时间: |
|
| 查看次数: |
12904 次 |
| 最近记录: |