Citrix ShareFile API上传Blob文件生成0字节文件问题求助
问题背景
通过REST API在Citrix ShareFile上传文件的流程分为4步:
- 获取access_token
- 获取文件夹URI确定上传目标
- 获取Chunk Uri
- 通过Chunk Uri上传文件
前3步执行完全正常,但第4步POST请求后,ShareFile中创建的文件大小为0字节。已在Postman中用form-data选择文件测试,上传功能正常,问题仅出现在上传Salesforce数据库中存储的Blob数据时(无法获取物理文件路径)。
正常执行的代码(前3步)
String fileName_m = 'a12.pdf'; // 获取认证Token HttpRequest req = new HttpRequest(); req.setEndpoint('https://{server}.sf-api.com/oauth/token?grant_type=password&client_id={client_id}&client_secret={secret}&username={user_name}&password={password}!'); req.setMethod('GET'); Http http = new Http(); HttpResponse response = http.send(req); System.Debug(response.getBody()); Map<String, Object> results = (Map<String, Object>)JSON.deserializeUntyped(response.getBody()); String token = ''; String refreshtoken = ''; if(response.getStatusCode() == 200){ token = (String)results.get('access_token'); refreshtoken = (String)results.get('refresh_token'); } system.debug('token=' + token); // 获取文件夹ID HttpRequest req1 = new HttpRequest(); req1.setEndpoint('https://{server}.sf-api.com/sf/v3/Items?$expand=Children'); req1.setMethod('GET'); req1.setHeader('Authorization','Bearer ' + token); Http http1 = new Http(); HttpResponse response1 = http1.send(req1); System.Debug(response1.getBody()); Map<String, Object> results1 = (Map<String, Object>)JSON.deserializeUntyped(response1.getBody()); String url = ''; if(response1.getStatusCode() == 200){ url = (String)results1.get('url'); } System.Debug('Folder Url ' + url); // 获取Chunk URI HttpRequest req2 = new HttpRequest(); String endPoint = url + '/Upload2'; req2.setEndpoint(endPoint); req2.setMethod('POST'); req2.setHeader('Authorization','Bearer ' + token); req2.setHeader('Content-Type', 'application/x-www-form-urlencoded'); String payload1 = 'FileName='+fileName_m; req2.setBody(payload1); Http http2 = new Http(); HttpResponse response2 = http2.send(req2); Map<String, Object> results2 = (Map<String, Object>)JSON.deserializeUntyped(response2.getBody()); String ChunkUri = ''; if(response2.getStatusCode() == 200){ ChunkUri = (String)results2.get('ChunkUri'); } System.Debug('ChunkUri' + ChunkUri);
出现问题的上传代码
// 问题出在这里,无法正常工作 // 上传文件 Attachment att = [SELECT Id, Body, Name, ContentType FROM Attachment WHERE Id='00P3p00001XNLOHEA5']; String body = EncodingUtil.base64Encode(att.body); List<Attachment> cvList = [SELECT Id, Body, Name, ContentType FROM Attachment WHERE Id='00P3p00001XNLOHEA5']; String attachmentBody = EncodingUtil.base64Encode(cvList[0].Body); Blob pdfBlob = EncodingUtil.base64Decode(attachmentBody); system.debug('pdfBlob' + pdfBlob); HttpRequest req3 = new HttpRequest(); req3.setEndpoint(ChunkUri); req3.setMethod('POST'); req3.setHeader('Authorization','Bearer ' + token); req3.setHeader('Content-Length', String.valueOf(attachmentBody.length())); req3.setHeader('Content-Encoding', 'UTF-8'); req3.setHeader('Content-type', 'application/pdf'); req3.setHeader('Connection', 'keep-alive'); req3.setBodyAsBlob(pdfBlob); Http http3 = new Http(); HttpResponse response3 = http3.send(req3); System.Debug(response3.getBody());
解决方案
1. 修正Content-Length计算错误
当前代码用attachmentBody.length()(Base64字符串长度)作为Content-Length,但实际应该用Blob的原始字节长度,也就是pdfBlob.size()。ShareFile会根据Content-Length判断接收的字节数,长度不匹配会导致只接收0字节。
2. 移除不必要的Content-Encoding头
你上传的是原始PDF二进制数据,不是UTF-8编码的文本,Content-Encoding: UTF-8会导致ShareFile解析错误,应该删除这个头。
3. 简化Blob获取逻辑
不需要重复查询Attachment并进行Base64编码解码,直接使用查询到的Blob即可,减少冗余操作。
修正后的上传代码
// 修正后的上传文件代码 Attachment att = [SELECT Id, Body, Name, ContentType FROM Attachment WHERE Id='00P3p00001XNLOHEA5']; Blob pdfBlob = att.Body; HttpRequest req3 = new HttpRequest(); req3.setEndpoint(ChunkUri); req3.setMethod('POST'); req3.setHeader('Authorization','Bearer ' + token); req3.setHeader('Content-Length', String.valueOf(pdfBlob.size())); req3.setHeader('Content-type', att.ContentType); // 使用Attachment自带的ContentType更准确 req3.setBodyAsBlob(pdfBlob); Http http3 = new Http(); HttpResponse response3 = http3.send(req3); System.Debug(response3.getBody());
额外验证点
- 确认Chunk Uri是否包含正确的上传参数(如文件大小、分片信息),如果是大文件可能需要分块上传,但小文件场景下当前逻辑足够。
- 检查Salesforce的Attachment是否确实有有效数据(
att.Body.size()大于0),避免源Blob本身为空。
内容的提问来源于stack exchange,提问作者Noor A Shuvo
相关产品推荐
相关产品推荐

