使用 multipart-form 将文件上传到 Salesforce
Upload a file to Salesforce using multipart-form
我正在尝试将文本文件(也尝试过 PDF 等)上传到 Salesforce。
文本文件包含 'hello world'.
这是我使用的代码
def putFile(sf, libname, filen):
file_name=os.path.basename(filen)
libId=libraryExists(sf, libname)
contentDocumentId = getContentDocumentId(sf, libname, file_name)
if not libId:
print(f"Provided library '{libname}' does not exists")
return
with open(filen, "rb") as f:
bodyEncoded = base64.b64encode(f.read())
boundary = '----------------------------741e90d31eff'
headers = {
'Content-Type' : 'multipart/form-data; boundary=' + boundary
}
nonBinaryPart = '--'+boundary+'\nContent-Disposition: form-data; name="entity_content";\n'
nonBinaryPart += 'Content-Type: application/json;\r\n\r\n'
nonBinaryPart += json.dumps({
"ContentDocumentId" : contentDocumentId,
"ReasonForChange" : "Large file upload",
"PathOnClient" : file_name
})
nonBinaryPart += '\r\n\r\n'
header = '--'+boundary+'\nContent-Disposition: form-data; name="VersionData"; filename="'+file_name+'";\nContent-Type: application/octet-stream\r\n\r\n'
footer = '--'+boundary+'--'
headerEncoded = header
last4Bytes = bodyEncoded[len(bodyEncoded)-4:len(bodyEncoded)]
print(type(last4Bytes))
print(last4Bytes)
if last4Bytes.endswith(b'=='):
last4Bytes = last4Bytes[0:2] + b'0K'
bodyEncoded = bodyEncoded[0:len(bodyEncoded)-4] + last4Bytes
footerEncoded = footer
reqBody = headerEncoded+str(bodyEncoded)+footerEncoded
elif last4Bytes.endswith(b'='):
print('Ends with =')
last4Bytes = last4Bytes[0:3] + b'N'
bodyEncoded = bodyEncoded[0:len(bodyEncoded)-4] + last4Bytes
footer = '\n' + footer;
footerEncoded = footer
reqBody = headerEncoded+str(bodyEncoded)+footerEncoded
else:
footer = '\r\n' + footer
footerEncoded = footer
reqBody = headerEncoded+str(bodyEncoded)+footerEncoded
reqBody = nonBinaryPart + reqBody
print('==================================================')
print(reqBody)
print('==================================================')
res = sf.contentVersion.create(reqBody, headers)
print(res)
print('Now downloading it...')
os.system('rm -f ' + filen + '_downloaded')
getFile(sf, contentDocumentId, filen + '_downloaded', './' )
print('Downloaded.')
os.system('md5sum ' + filen)
os.system('md5sum ' + filen + '_downloaded')
这会导致以下请求 body,这似乎符合 Salesforce 指南:
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm
Headers:
Content-Type: multipart/form-data; boundary="----------------------------741e90d31eff"
接受:application/json
请求body:
--------------------------------741e90d31eff
Content-Disposition: form-data;名字="entity_content";
Content-Type: application/json;
{"ContentDocumentId": "0699E000000lKbLQAU", "ReasonForChange": "Large file upload", "PathOnClient": "hello_world.txt"}
--------------------------------741e90d31eff
Content-Disposition: form-data;名字="VersionData";文件名="hello_world.txt";
Content-Type: application/octet-stream
b'aGVsbG8gd29ybGQK'
------------------------------741e90d31eff--
如您的代码所示 bodyEncoded = base64.b64encode(f.read())
,文件以 base64 编码发送。下载文件后需要对其进行解码以恢复其原始 "readable" 值。
注意:正如你的评论所说,你的文件内容是b'aGVsbG8gd29ybGQK'
,其中b
表示一个base64编码的字符串,另一个部分是编码值,您也可以使用 base64decode 等在线工具对其进行编码,这将显示该字符串正好是 hello world
我终于明白了。因此,要将多部分表单数据上传到 Salesforce:
1.没有base64编码!!!!
它需要保持二进制
2. 我的错误是我试图将字符串连接到字节。
因此,构建多部分消息的非二进制部分并将其编码为二进制:
nonbinaryPart.encode()
- 比将字节附加到字节,文件的二进制内容。
- 调用api时,post数据为字节。请注意 API 的用法,例如 simple-salsforce 默认情况下可能希望将其编码为 json。不需要后续编码。 Post 作为二进制。
我正在尝试将文本文件(也尝试过 PDF 等)上传到 Salesforce。 文本文件包含 'hello world'.
这是我使用的代码
def putFile(sf, libname, filen):
file_name=os.path.basename(filen)
libId=libraryExists(sf, libname)
contentDocumentId = getContentDocumentId(sf, libname, file_name)
if not libId:
print(f"Provided library '{libname}' does not exists")
return
with open(filen, "rb") as f:
bodyEncoded = base64.b64encode(f.read())
boundary = '----------------------------741e90d31eff'
headers = {
'Content-Type' : 'multipart/form-data; boundary=' + boundary
}
nonBinaryPart = '--'+boundary+'\nContent-Disposition: form-data; name="entity_content";\n'
nonBinaryPart += 'Content-Type: application/json;\r\n\r\n'
nonBinaryPart += json.dumps({
"ContentDocumentId" : contentDocumentId,
"ReasonForChange" : "Large file upload",
"PathOnClient" : file_name
})
nonBinaryPart += '\r\n\r\n'
header = '--'+boundary+'\nContent-Disposition: form-data; name="VersionData"; filename="'+file_name+'";\nContent-Type: application/octet-stream\r\n\r\n'
footer = '--'+boundary+'--'
headerEncoded = header
last4Bytes = bodyEncoded[len(bodyEncoded)-4:len(bodyEncoded)]
print(type(last4Bytes))
print(last4Bytes)
if last4Bytes.endswith(b'=='):
last4Bytes = last4Bytes[0:2] + b'0K'
bodyEncoded = bodyEncoded[0:len(bodyEncoded)-4] + last4Bytes
footerEncoded = footer
reqBody = headerEncoded+str(bodyEncoded)+footerEncoded
elif last4Bytes.endswith(b'='):
print('Ends with =')
last4Bytes = last4Bytes[0:3] + b'N'
bodyEncoded = bodyEncoded[0:len(bodyEncoded)-4] + last4Bytes
footer = '\n' + footer;
footerEncoded = footer
reqBody = headerEncoded+str(bodyEncoded)+footerEncoded
else:
footer = '\r\n' + footer
footerEncoded = footer
reqBody = headerEncoded+str(bodyEncoded)+footerEncoded
reqBody = nonBinaryPart + reqBody
print('==================================================')
print(reqBody)
print('==================================================')
res = sf.contentVersion.create(reqBody, headers)
print(res)
print('Now downloading it...')
os.system('rm -f ' + filen + '_downloaded')
getFile(sf, contentDocumentId, filen + '_downloaded', './' )
print('Downloaded.')
os.system('md5sum ' + filen)
os.system('md5sum ' + filen + '_downloaded')
这会导致以下请求 body,这似乎符合 Salesforce 指南: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm
Headers:
Content-Type: multipart/form-data; boundary="----------------------------741e90d31eff" 接受:application/json
请求body:
--------------------------------741e90d31eff Content-Disposition: form-data;名字="entity_content"; Content-Type: application/json;
{"ContentDocumentId": "0699E000000lKbLQAU", "ReasonForChange": "Large file upload", "PathOnClient": "hello_world.txt"}
--------------------------------741e90d31eff Content-Disposition: form-data;名字="VersionData";文件名="hello_world.txt"; Content-Type: application/octet-stream
b'aGVsbG8gd29ybGQK' ------------------------------741e90d31eff--
如您的代码所示 bodyEncoded = base64.b64encode(f.read())
,文件以 base64 编码发送。下载文件后需要对其进行解码以恢复其原始 "readable" 值。
注意:正如你的评论所说,你的文件内容是b'aGVsbG8gd29ybGQK'
,其中b
表示一个base64编码的字符串,另一个部分是编码值,您也可以使用 base64decode 等在线工具对其进行编码,这将显示该字符串正好是 hello world
我终于明白了。因此,要将多部分表单数据上传到 Salesforce: 1.没有base64编码!!!! 它需要保持二进制 2. 我的错误是我试图将字符串连接到字节。 因此,构建多部分消息的非二进制部分并将其编码为二进制:
nonbinaryPart.encode()
- 比将字节附加到字节,文件的二进制内容。
- 调用api时,post数据为字节。请注意 API 的用法,例如 simple-salsforce 默认情况下可能希望将其编码为 json。不需要后续编码。 Post 作为二进制。