Salesforce Apex调用Zalo文件上传API时提示‘File not exist’问题
问题:调用Zalo文件上传API返回"File not exist!"错误
开发Zalo API获取文件令牌时,Apex代码调用后API返回状态码200,但响应体提示文件不存在:
{"error":-201,"message":"File not exist!"}
现有Apex代码
String fileId = '069HE0000010ZurYAE'; // contentDocumentId String fileName = 'file-sample_150kB.pdf'; ContentVersion contentVersion = [SELECT Id, ContentSize, Title, ContentDocumentId, VersionData FROM ContentVersion WHERE ContentDocumentId = :fileId LIMIT 1]; Blob fileData = contentVersion.VersionData; String boundary = '----MyBoundary'; String requestBody = '--' + boundary + '\r\n' + 'Content-Disposition: form-data; name="field1"' + '\r\n' + '--' + boundary + '\r\n' + 'Content-Disposition: form-data; name="file"; filename="' + fileName + '"' + '\r\n' + 'Content-Type: application/octet-stream' + '\r\n' + '\r\n' + fileData + '\r\n' + '--' + boundary + '--' + '\r\n'; HttpRequest req = new HttpRequest(); req.setMethod('POST'); req.setEndpoint('https://openapi.zalo.me/v2.0/oa/upload/file'); req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); req.setHeader('access_token', <access_token_here>); req.setBody(requestBody); Http h = new Http(); HttpResponse response = h.send(req);
可正常运行的curl请求
curl --location 'openapi.zalo.me/v2.0/oa/upload/file' \ --header 'access_token: <access_token_here>' \ --header 'Accept: application/json' \ --form 'file="@/C:/Users/Desktop/Sample Files/file-sample_150kB.pdf"'
该curl请求在Postman中可正常执行,但Apex代码调用报错。
问题原因
Apex中直接将Blob类型的文件数据与字符串拼接时,二进制数据会被强制转换为UTF-8字符串,导致文件内容损坏。Zalo API无法识别损坏的文件数据,因此返回"File not exist!"错误。
解决方案
使用HttpRequest.setBodyAsBlob()构建完整的二进制请求体,避免字符串与Blob拼接导致的编码问题。修正后的代码如下:
String fileId = '069HE0000010ZurYAE'; // contentDocumentId String fileName = 'file-sample_150kB.pdf'; ContentVersion contentVersion = [SELECT Id, ContentSize, Title, ContentDocumentId, VersionData FROM ContentVersion WHERE ContentDocumentId = :fileId LIMIT 1]; Blob fileData = contentVersion.VersionData; String boundary = '----MyBoundary'; // 构建表单字段部分(不需要可删除) String fieldPart = '--' + boundary + '\r\n' + 'Content-Disposition: form-data; name="field1"\r\n\r\n' + 'your_field_value\r\n'; // 替换为field1的实际值 // 构建文件部分的头部 String fileHeaderPart = '--' + boundary + '\r\n' + 'Content-Disposition: form-data; name="file"; filename="' + fileName + '"\r\n' + 'Content-Type: application/octet-stream\r\n\r\n'; // 构建请求体结尾 String footerPart = '\r\n--' + boundary + '--\r\n'; // 将所有部分转换为Blob并拼接 Blob requestBodyBlob = Blob.valueOf(fieldPart) + Blob.valueOf(fileHeaderPart) + fileData + Blob.valueOf(footerPart); HttpRequest req = new HttpRequest(); req.setMethod('POST'); req.setEndpoint('https://openapi.zalo.me/v2.0/oa/upload/file'); req.setHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); req.setHeader('access_token', '<access_token_here>'); req.setBodyAsBlob(requestBodyBlob); // 用二进制方式传递请求体 Http h = new Http(); HttpResponse response = h.send(req);
关键说明
- 禁止直接将Blob与字符串拼接,二进制文件转字符串会导致数据丢失或损坏
- 使用
setBodyAsBlob()传递完整的二进制请求体,确保文件数据原样传输 - 若不需要
field1参数,可删除对应的fieldPart,调整requestBodyBlob的拼接逻辑即可
内容的提问来源于stack exchange,提问作者Nisha Sharma
相关产品推荐
相关产品推荐

