在以前的项目中,我通常让前端先将图片上传到自己的服务器,再由服务器将图片转发到七牛云。这种做法虽然控制权完全在后端,但中间多了一次转发,增加了带宽和延迟,也让架构变得复杂。
其实,七牛云官方早已提供了前端直传的方式,不经过自己的服务器也能安全上传。最开始我对此心存疑虑,担心会泄露权限或被滥用。但深入了解之后,我发现这种方式不仅安全可靠,还是官方推荐的最佳实践。
第一步:后端生成上传凭证
前端直传的核心是:前端不能直接拥有七牛云的密钥(Access Key / Secret Key) ,但它可以使用后端生成的「一次性上传凭证」(Upload Token)。
// 需要安装七牛 Node.js SDK:npm install qiniu
import qiniu from 'qiniu';
// 你的七牛云 Access Key 和 Secret Key
const accessKey = '你的AccessKey';
const secretKey = '你的SecretKey';
const bucket = '你的Bucket名称';
// 初始化授权对象
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
function generateUploadToken(key: string) {
const putPolicy = new qiniu.rs.PutPolicy({
scope: `${bucket}:${key}`, // 限定只能上传到指定 key
expires: 3600, // Token 有效时间(单位:秒)
returnBody: JSON.stringify({
size: "$(fsize)",
width: "$(imageInfo.width)",
height: "$(imageInfo.height)",
mimeType: "$(mimeType)",
}), // 上传成功后返回的 JSON
insertOnly: 1, // 只允许插入新文件(防止覆盖)
mimeLimit: "image/*", // 限制只允许上传图片
fsizeLimit: 10 * 1024 * 1024, // 文件大小上限为 10MB
});
const uploadToken = putPolicy.uploadToken(mac);
return {
token: uploadToken,
key: key, // 返回给前端的文件 key(前端上传时需要)
};
}
你可以将这个接口部署在后端的 /api/qiniu-token 路由上,前端上传前来获取一次性凭证
第二步:前端使用上传 Token 上传图片
获取 Token 后,前端就可以使用 fetch 或其他方式将文件上传到七牛云的上传地址。
前端上传示例代码
async function uploadToQiniu() {
const fileInput = document.getElementById('fileInput');
const file = fileInput?.files?.[0];
if (!file) {
alert('请选择文件');
return;
}
// 请求后端上传凭证
const resp = await fetch('/api/qiniu-token');
const { token, key } = await resp.json();
const formData = new FormData();
formData.append('file', file);
formData.append('token', token);
formData.append('key', key); // key 必须和 token 中设置的一致
// 上传到七牛云,注意选择与你存储区域对应的上传域名
const uploadResp = await fetch('https://up-z2.qiniup.com/', {
method: 'POST',
body: formData,
});
if (uploadResp.ok) {
const result = await uploadResp.json();
console.log('上传成功:', result);
} else {
console.error('上传失败');
}
}
上传地址 https://up-z2.qiniup.com/ 对应的是华南区域。如果你的空间属于其他区域,请使用对应的上传域名。可参考七牛云的存储区域_产品简介_对象存储 - 七牛开发者中心。