You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Visualforce与Apex上传图片至S3后无法正常显示如何解决?

你代码存在3个核心问题,直接导致上传到S3的文件不是合法的图片格式:

  • 没有移除DataURL的base64前缀:JS通过readAsDataURL获取的结果自带data:image/png;base64,格式的前缀,你直接将完整字符串传到后端处理,前缀会被当成图片内容的一部分,导致最终生成的二进制文件不是合法的图片格式。
  • Apex侧存在多余的二次编码:你拿到传入的base64字符串后,先调用Blob.valueOf()转换为二进制,再重新做base64编码,相当于对原内容做了二次编码,彻底破坏了原图片的二进制结构。
  • Content-Length计算错误:你传入的是base64字符串的长度,但实际发送给S3的是解码后的二进制Blob,两者长度完全不匹配,S3会判定内容存在异常。

修正方案

1. 前端Visualforce代码修正

补全FileReader的初始化逻辑,同时移除DataURL的前缀,只将纯base64内容传到后端:

<input class="slds-input-custom" id="logo" name="bsLogo" type="file" />
<button id="submtBtn" onclick="toSubmit()" label="Submit" title="Submit" class="cSubmit"  >Submit</button>
<apex:form id="formId">
    <apex:actionFunction name="setParamAF" action="{!apexMethod}" rerender="panelId" status="checkingId" oncomplete="onloadCallback();">
            <apex:param name="vBusiLogo" value=""/>
    </apex:actionFunction>
</apex:form>

<script>
   function toSubmit(){
       const selectFile = document.getElementById('logo').files[0];
       if(!selectFile) return;
       // 补全FileReader实例初始化
       const reader = new FileReader();
       reader.readAsDataURL(selectFile);
       reader.onload = function(){
           const dataURL = reader.result;
           // 移除base64前缀,仅传递纯编码内容
           const pureBase64 = dataURL.split(',')[1];
           setParamAF(pureBase64);
       };
   }
   function onloadCallback(){
       alert('uploaded');
   }
</script>

2. 后端Apex代码修正

去掉多余的编码步骤,直接解码传入的纯base64内容,同时修正Content-Length的取值,删除无效的Content-Encoding头:

String busiLogo = '';
public static void apexMethod(){
  busiLogo = ApexPages.currentPage().getParameters().get('vBusiLogo');
  String logoName = 'image.png';
  String bucketname ='amazon-file-s3';
  String host = 's3-ap-sample-1.amazonaws.com';

  // 直接解码纯base64内容得到原图片二进制
  Blob blobFile = EncodingUtil.base64Decode(busiLogo);
    HttpRequest req = new HttpRequest();
    req.setMethod('PUT');
    req.setEndpoint('callout:AmazonS3' + '/' + logoName);
    req.setHeader('Host', bucketname + '.' + host);
    // 用解码后的二进制实际长度作为Content-Length值
    req.setHeader('Content-Length', String.valueOf(blobFile.size()));
    req.setHeader('Content-Type','image/png');
    req.setHeader('Connection', 'keep-alive');
    req.setHeader('Date', formattedDateString);
    req.setHeader('ACL', 'public-read-write');
    req.setBodyAsBlob(blobFile);
    
    Http http = new Http();
    HTTPResponse res = http.send(req);
}

其他注意事项

如果上传的图片格式不固定为PNG,可以在JS中同时传递文件的MIME类型到Apex,动态设置Content-Type头,适配不同格式的文件。
可以在Apex中打印传入的busiLogo内容,确认前缀已经被完全移除,避免多余字符混入图片二进制。

内容的提问来源于stack exchange,提问作者Leonard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:15:05