无法将图像二进制文件添加到 multipart/form-data
unable to add image binary into multipart/form-data
我收到一个错误:预期的 str 实例,当我尝试将图像二进制文件添加到 multipart/form-data 时发现的字节。
问题是我试图将二进制格式的图像数据附加到字符串。有没有办法将二进制图像添加到 multipart/form 数据?
我束手无策,希望能为此提供一些帮助。
imageData = request.FILES['filePath'].read()
content_type, request_body = encode_multipart_formdata([('include_target_data', targetMetaDataRet),
('max_num_results', str(maxNoResultRet))],
[('image', imagePath, imageData)])
def encode_multipart_formdata(fields, files):
BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
CRLF = '\r\n'
lines = []
for (key, value) in fields:
lines.append('--' + BOUNDARY)
lines.append('Content-Disposition: form-data; name="%s"' % key)
lines.append('')
lines.append(value)
for (key, filename, value) in files:
lines.append('--' + BOUNDARY)
lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
lines.append('Content-Type: %s' % get_content_type(filename))
lines.append('')
lines.append(value)
lines.append('--' + BOUNDARY + '--')
lines.append('')
body = CRLF.join(lines)
content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
return content_type, body
回溯:
35. response = get_response(request)
128. response = self.process_exception_by_middleware(e, request)
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
166. [('image', imagePath, imageData)])
232. body = CRLF.join(lines)
Exception Type: TypeError at /identify_shrine
Exception Value: sequence item 12: expected str instance, bytes found
根据@coltoneakins 的请求,我将请求正文修改为字节,但我似乎遇到了错误的请求错误,知道为什么吗?
代码:
content_type = 'multipart/form-data; boundary=----------ThIs_Is_tHe_bouNdaRY_$'
request_body = '----------ThIs_Is_tHe_bouNdaRY_$' + '\n'+'Content-Disposition: form-data; name="include_target_data"' + '\n' + '\n' + 'top'+ '\n' + '----------ThIs_Is_tHe_bouNdaRY_$' +'\n' + 'Content-Disposition: form-data; name="max_num_results"' + '\n' + '\n' + '1' + '\n' + '----------ThIs_Is_tHe_bouNdaRY_$' +'\n' + 'Content-Disposition: form-data; name="image"; filename="img_2.jpg"' + '\n' + 'Content-Type: image/jpeg' + '\n' + '\n'
request_body1 = request_body.encode('utf-8')
request_body2 = imageData
request_body3 = ('\n' + '\n' + '----------ThIs_Is_tHe_bouNdaRY_$').encode('utf-8')
request_body4 = request_body1 + request_body2 + request_body3
content_type_bare = 'multipart/form-data'
# Sign the request and get the Authorization header
# use client key
auth_header = authorization_header_for_request(CLIENT_ACCESS_KEY, CLIENT_SECRET_KEY, HTTP_METHOD, request_body4,
content_type_bare,
date, path)
request_headers = {
'Accept': 'application/json',
'Authorization': auth_header,
'Content-Type': content_type,
'Date': date
}
try:
# Make the request over HTTPS on port 443
connection = http.client.HTTPSConnection(CLOUD_RECO_API_ENDPOINT, 443)
connection.request(HTTP_METHOD, path, request_body4, request_headers)
response = connection.getresponse()
response_body = response.read()
reason = response.reason
status = response.status
finally:
connection.close()
您的代码中存在类型问题。你得到一个 TypeError expected str instance, bytes found 因为你试图 join() 一个包含两个 str 的列表 类型和 Python 中的 字节 类型。
查看代码中的这些行:
for (key, filename, value) in files:
lines.append('--' + BOUNDARY)
lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
lines.append('Content-Type: %s' % get_content_type(filename))
lines.append('')
lines.append(value) # <---------- THIS IS BYTES, EVERYTHING ELSE IS STR
lines.append('--' + BOUNDARY + '--')
lines.append('')
body = CRLF.join(lines) # <---------- AHHH RED FLAG!!!
CRLF 是类型 str。但是,value(添加到您的 lines 列表中)是 bytes。这意味着您最终得到包含 str 和 bytes 类型的 lines。当您通过 mulitpart/form-data 请求发送图像时,请求的整个主体都是字节。因此,您只需要将 join() 与 bytes 类型一起使用。
这就是你正在做的事情:
body = CRLF.join(lines)
这是真的:
'\r\n, i am a str'.join(['i am also str', b'I am not a str, I am bytes']) # <-- NO
这是你需要做的:
b'I am bytes'.join([b'I am also bytes', b'Me too!'])
另外,请注意,Requests 库为您提供了发送文件的机制。请参阅 files parameter in the Requests documentation 或这个 Whosebug 答案:
因此,您可能不需要在这里重新发明轮子。 Requests 将对文件进行多部分编码并为您构建请求。
我收到一个错误:预期的 str 实例,当我尝试将图像二进制文件添加到 multipart/form-data 时发现的字节。
问题是我试图将二进制格式的图像数据附加到字符串。有没有办法将二进制图像添加到 multipart/form 数据?
我束手无策,希望能为此提供一些帮助。
imageData = request.FILES['filePath'].read()
content_type, request_body = encode_multipart_formdata([('include_target_data', targetMetaDataRet),
('max_num_results', str(maxNoResultRet))],
[('image', imagePath, imageData)])
def encode_multipart_formdata(fields, files):
BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
CRLF = '\r\n'
lines = []
for (key, value) in fields:
lines.append('--' + BOUNDARY)
lines.append('Content-Disposition: form-data; name="%s"' % key)
lines.append('')
lines.append(value)
for (key, filename, value) in files:
lines.append('--' + BOUNDARY)
lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
lines.append('Content-Type: %s' % get_content_type(filename))
lines.append('')
lines.append(value)
lines.append('--' + BOUNDARY + '--')
lines.append('')
body = CRLF.join(lines)
content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
return content_type, body
回溯:
35. response = get_response(request)
128. response = self.process_exception_by_middleware(e, request)
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
166. [('image', imagePath, imageData)])
232. body = CRLF.join(lines)
Exception Type: TypeError at /identify_shrine
Exception Value: sequence item 12: expected str instance, bytes found
根据@coltoneakins 的请求,我将请求正文修改为字节,但我似乎遇到了错误的请求错误,知道为什么吗?
代码:
content_type = 'multipart/form-data; boundary=----------ThIs_Is_tHe_bouNdaRY_$'
request_body = '----------ThIs_Is_tHe_bouNdaRY_$' + '\n'+'Content-Disposition: form-data; name="include_target_data"' + '\n' + '\n' + 'top'+ '\n' + '----------ThIs_Is_tHe_bouNdaRY_$' +'\n' + 'Content-Disposition: form-data; name="max_num_results"' + '\n' + '\n' + '1' + '\n' + '----------ThIs_Is_tHe_bouNdaRY_$' +'\n' + 'Content-Disposition: form-data; name="image"; filename="img_2.jpg"' + '\n' + 'Content-Type: image/jpeg' + '\n' + '\n'
request_body1 = request_body.encode('utf-8')
request_body2 = imageData
request_body3 = ('\n' + '\n' + '----------ThIs_Is_tHe_bouNdaRY_$').encode('utf-8')
request_body4 = request_body1 + request_body2 + request_body3
content_type_bare = 'multipart/form-data'
# Sign the request and get the Authorization header
# use client key
auth_header = authorization_header_for_request(CLIENT_ACCESS_KEY, CLIENT_SECRET_KEY, HTTP_METHOD, request_body4,
content_type_bare,
date, path)
request_headers = {
'Accept': 'application/json',
'Authorization': auth_header,
'Content-Type': content_type,
'Date': date
}
try:
# Make the request over HTTPS on port 443
connection = http.client.HTTPSConnection(CLOUD_RECO_API_ENDPOINT, 443)
connection.request(HTTP_METHOD, path, request_body4, request_headers)
response = connection.getresponse()
response_body = response.read()
reason = response.reason
status = response.status
finally:
connection.close()
您的代码中存在类型问题。你得到一个 TypeError expected str instance, bytes found 因为你试图 join() 一个包含两个 str 的列表 类型和 Python 中的 字节 类型。
查看代码中的这些行:
for (key, filename, value) in files:
lines.append('--' + BOUNDARY)
lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
lines.append('Content-Type: %s' % get_content_type(filename))
lines.append('')
lines.append(value) # <---------- THIS IS BYTES, EVERYTHING ELSE IS STR
lines.append('--' + BOUNDARY + '--')
lines.append('')
body = CRLF.join(lines) # <---------- AHHH RED FLAG!!!
CRLF 是类型 str。但是,value(添加到您的 lines 列表中)是 bytes。这意味着您最终得到包含 str 和 bytes 类型的 lines。当您通过 mulitpart/form-data 请求发送图像时,请求的整个主体都是字节。因此,您只需要将 join() 与 bytes 类型一起使用。
这就是你正在做的事情:
body = CRLF.join(lines)
这是真的:
'\r\n, i am a str'.join(['i am also str', b'I am not a str, I am bytes']) # <-- NO
这是你需要做的:
b'I am bytes'.join([b'I am also bytes', b'Me too!'])
另外,请注意,Requests 库为您提供了发送文件的机制。请参阅 files parameter in the Requests documentation 或这个 Whosebug 答案:
因此,您可能不需要在这里重新发明轮子。 Requests 将对文件进行多部分编码并为您构建请求。