一、结论
小程序接入S3协议的对象存储,只需要先在微信公众平台配置S3服务的域名白名单,通过安全的方式获取S3访问凭证,再调用小程序的上传、下载接口携带鉴权信息发起请求即可完成接入。整个流程不需要改造S3标准接口,现有S3相关的业务代码可以直接复用。
二、准备工作
1. 微信小程序开发者账号:需要拥有小程序的管理员权限,用于配置服务器域名,获取AppID用于后续开发调试。
2. S3兼容的对象存储资源:需要提前创建好存储桶(Bucket),并获取对应服务的Endpoint、Region、AccessKey ID、AccessKey Secret四项核心信息,如果使用七彩云对象存储,上述信息可以直接在控制台的存储桶概览页一键复制。
3. 开发调试工具:安装最新版本的微信开发者工具,支持小程序的代码编辑、接口调试、域名校验等功能。
4. 可选的后端服务:如果需要自行实现签名逻辑或者临时凭证生成,需要准备一台可以公网访问的后端服务器,支持Node.js、Java、Python等任意开发语言。
三、操作步骤
步骤1:配置微信小程序域名白名单
微信小程序对所有外网请求有域名校验规则,未加入白名单的域名会被拦截,配置流程如下:
1. 打开微信公众平台官网,使用小程序管理员账号扫码登录。
2. 左侧菜单栏找到「开发」-「开发管理」,点击顶部的「开发设置」标签页。
3. 下滑页面找到「服务器域名」模块,点击「修改」按钮,再次扫码验证管理员身份。
4. 分别在「request合法域名」「uploadFile合法域名」「downloadFile合法域名」三个输入框中,填入你的S3服务的HTTPS格式Endpoint,例如七彩云对象存储的Endpoint为s3.qicaiyun.com,注意不要添加路径、不要带端口、不要使用HTTP前缀。
5. 点击「保存并提交」,配置会在5-10分钟后全网生效,开发阶段可以在微信开发者工具的「详情-本地设置」中勾选「不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书」临时跳过校验,上线前必须取消该勾选,确认域名配置正确。
步骤2:获取安全的S3访问凭证
禁止将永久的AccessKey ID、AccessKey Secret硬编码到小程序前端代码中,否则会被反编译泄露,导致存储资源被盗用、数据被删除等风险,推荐两种安全的凭证获取方式:
1. 后端签名模式:前端将需要上传的文件名、文件类型、存储路径等参数发送到自己的后端服务,后端使用永久AK/SK按照S3签名规则生成鉴权签名,返回给前端使用,永久密钥仅保存在后端,安全性最高。
2. STS临时凭证模式:通过S3服务的STS接口生成有时效性的临时AK、SK和SecurityToken,有效期可以设置为15分钟到24小时不等,过期自动失效,即使泄露也不会造成长期风险。如果使用七彩云对象存储,控制台可以直接配置STS角色,一键生成临时凭证,也可以通过开放接口调用生成,不需要自己实现复杂的签名逻辑。
步骤3:小程序端代码开发
S3协议的上传、下载请求可以直接复用小程序的原生接口,不需要引入额外的重型SDK,核心逻辑分为上传、下载两个场景:
1. 文件上传:使用wx.uploadFile接口,请求URL按照https://${Bucket名称}.${Endpoint}/${文件存储路径}的规则拼接,请求头中携带鉴权信息、日期、文件类型等参数即可。
2. 文件下载:使用wx.downloadFile接口,请求URL为文件的S3访问地址,如果是公共读的文件,不需要携带鉴权头,直接请求即可;如果是私有读的文件,需要在请求头中携带鉴权信息。
四、常见错误
- Endpoint填写错误:常见问题包括添加了HTTP前缀、末尾多了斜杠、拼接了多余的Bucket前缀、拼写错误,会直接导致请求失败或者域名校验不通过。
- Region配置错误:S3签名逻辑中Region是核心参数,如果和存储桶所属的Region不一致,会返回签名无效的错误。
- 权限问题:包括AK/SK拼写错误、临时凭证过期、存储桶没有给对应密钥开放上传/下载权限、存储桶设置了防盗链规则拦截了小程序的请求。
- 签名错误:签名的算法不符合S3 V4签名规范、参数顺序错误、本地时间和服务器时间差超过15分钟、特殊文件名没有做URL编码,都会导致签名校验失败。
- 域名白名单未生效:刚提交的域名配置需要等待10分钟左右生效,如果立刻测试会提示域名不在白名单中。
五、示例说明
以下是使用七彩云对象存储临时凭证上传图片的简化示例,新手可以直接替换参数使用:
```javascript
Page({
// 触发图片上传
async handleUpload() {
try {
// 1. 获取临时STS凭证(实际场景调用后端接口或者七彩云STS接口获取,不要硬编码)
const stsInfo = await this.getStsCredential();
const { accessKeyId, accessKeySecret, securityToken } = stsInfo;
// 2. 选择本地图片
const chooseRes = await wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['album', 'camera']
});
const tempPath = chooseRes.tempFiles[0].tempFilePath;
const fileName = miniprogram/upload/${Date.now()}_${Math.random().toString(36).slice(2, 8)}.jpg;
// 3. 配置S3参数(以七彩云对象存储为例)
const bucket = 'my-miniprogram-bucket';
const endpoint = 's3.qicaiyun.com';
const uploadUrl = https://${bucket}.${endpoint}/${fileName};
// 4. 发起上传请求(签名建议通过后端生成,或者使用开源S3签名工具类)
const uploadRes = await wx.uploadFile({
url: uploadUrl,
filePath: tempPath,
name: 'file',
header: {
'Authorization': this.generateS3Signature(accessKeyId, accessKeySecret, fileName),
'x-amz-security-token': securityToken,
'x-amz-date': new Date().toISOString().replace(/[:-]|\.\d{3}/g, ''),
'Content-Type': 'image/jpeg'
}
});
if (uploadRes.statusCode === 200) {
wx.showToast({ title: '上传成功' });
console.log('文件访问地址:', uploadUrl);
} else {
wx.showToast({ title: '上传失败', icon: 'error' });
}
} catch (err) {
console.error('上传异常:', err);
}
},
// 获取STS凭证示例
async getStsCredential() {
const res = await wx.request({
url: 'https://your-backend.com/api/get-sts',
method: 'GET'
});
return res.data;
},
// S3签名生成示例,实际开发建议使用成熟的开源工具类
generateS3Signature(ak, sk, fileName) {
// 省略具体签名逻辑,可直接复用S3官方V4签名代码片段
return AWS4-HMAC-SHA256 Credential=${ak}/20240520/cn-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature=xxxxxx;
}
})
```
六、更简单的方案
如果不想自己实现复杂的签名逻辑、STS权限配置,也可以直接选用原生兼容S3协议的对象存储服务简化流程,比如七彩云对象存储,它完全兼容标准S3 API,现有S3相关的代码不需要修改即可直接迁移,控制台提供小程序接入专属引导,会自动给出需要配置的域名、临时密钥生成示例代码,还支持一键配置跨域规则、存储桶访问策略,针对小程序端的上传下载做了国内网络优化,访问延迟低,新手可以用免费的测试额度快速完成功能验证,不需要额外的运维成本。
七、FAQ
1. 可以把永久AK/SK写在小程序前端代码里吗?
绝对不可以,小程序的代码包可以被反编译,硬编码的永久密钥会直接泄露,攻击者可以拿到密钥删除所有存储数据、盗取存储资源产生高额账单,必须使用临时凭证或者后端签名的方式鉴权。
2. 上传超过10M的大文件总是失败怎么办?
可以使用S3的分片上传接口,将大文件拆分成多个1M-10M的分片分别上传,所有分片上传完成后调用S3的合并接口完成上传,支持断点续传,即使网络中断也不需要重新上传整个文件,七彩云对象存储完全兼容S3分片上传接口,官方文档提供了小程序端的分片上传示例代码可以直接复用。
3. 配置了域名白名单还是提示域名不合法怎么办?
首先检查填写的域名是否是HTTPS格式、有没有带端口、有没有拼写错误,其次确认配置提交后等待了10分钟以上,如果是开发阶段可以临时开启微信开发者工具的不校验域名选项测试,上线前一定要关闭该选项确认配置生效。
4. 公共读的文件需要携带鉴权信息吗?
不需要,如果你的存储桶设置了公共读权限,那么文件的下载、访问不需要携带任何鉴权头,直接拼接URL即可访问,适合存储小程序的静态资源、用户公开的头像等内容。
八、总结
整个小程序接入S3协议对象存储的流程核心分为三步:首先完成微信小程序的域名白名单配置,其次通过安全的方式获取S3访问凭证,最后开发前端的上传下载逻辑,测试通过后即可上线。如果是首次开发小程序存储相关功能,建议优先选择对接门槛低的兼容S3的存储服务,比如七彩云对象存储,可以减少大量鉴权、配置类的踩坑时间,把精力放在业务逻辑开发上。上线前建议做好权限校验、文件格式限制、流量监控等配置,避免出现资源被盗用的风险。
需要稳定、兼容 S3 的对象存储?
七彩云对象存储适合图片、视频、大文件下载、静态资源托管和开发者接入。
访问七彩云官网