实现阿里云OSS文件上传

鄢晔
2023-12-01

1.开通服务并获取配置

通过 对象存储OSS 购买服务后 ,该步骤主要配置 regionbucket ,再通过 AccessKey管理 获取到服务 accessKeyIdaccessKeySecret ,即得到如下信息:

{
  "region": "region",
  "bucket": "bucket",
  "AccessKey": "AccessKey",
  "accessKeySecret": "accessKeySecret",
  // 用于服务端签名后直传,设置上传回调
  "callback": "callback",
  // 用于服务端签名后直传,设置上传回调接口认证
  "x-csrf-token": "x-csrf-token"
}

服务器端签名直传,首先是后端会提供一个接口,前端请求该接口后会返回一些字段数据,即以上关键信息;

2.上传方案确认

  • 服务端验证上传

    先将文件传递到应用服务器,再由应用服务器上传至oss服务器,这种方式的优势是简单易懂,只须要按照文档使用ali-oss中间件上传就行,本文重点不放在这种方式;

    这种方式缺点是,文件要先上传到应用服务器,再上传到oss,占用带宽资源,过程简单,调用服务端接口;

  • 服务端签名前端直传

    在客户端通过JavaScript代码完成签名,无需过多配置,即可实现直传,非常方便。但是客户端通过JavaScript把AccesssKey ID和AccessKey Secret写在代码里面有泄露的风险,强烈建议使用服务端签名后直传或者STS临时授权访问OSS

    该方式分为两种上传方案:

    • 通过 oss-js-sdk ,即 ali-oss 上传文件;
    • 通过第三方请求工具上传,如 axioswx.uploadFile 等,本文主要对该方式进行配置说明;

3.配置说明

​ 通过第三方请求工具上传,如 axioswx.uploadFile 等;

​ 大多数情况下,用户上传数据后,应用服务器需要知道用户上传了哪些文件以及文件名;如果上传了图片,还需要知道图片的大小等,为此OSS提供了上传回调方案;

​ 具体参数说明,参考阿里云 - 帮助中心 - PostObject,必要配置参数如下:

{
  "OSSAccessKeyId": "OSSAccessKeyId",
  // 通过 crypto-js 生成,或直接从后端获取
  "policy": "policy",
  "success_action_status": "200",
  // 该参数为非必要参数,用于实现上传回调方案
  "callback": "callback",
  "name": "filename",
  "key": "application/${filename}",
  // 通过 crypto-js 生成,或直接从后端获取
  "Signature": "Signature",
}

4. 代码实现

1.oss-js-sdk

// npm install ali-oss --save
// <script type="text/javascript" src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.16.0.min.js"></script>

const client = new OSS({
	// yourregion填写Bucket所在地域。
	// 以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
	region: 'oss-cn-hangzhou',
	// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。
	// 强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
	accessKeyId: 'accessKeyId',
	accessKeySecret: 'accessKeySecret',
	// 填写Bucket名称。关于Bucket名称命名规范的更多信息,请参见Bucket。
	bucket: 'xx-bucket',
});

const headers = {
  ...
};

try {
	const result = await client.put(
		"application/exampleSmile.png",
		data
		// {headers}
	);
	console.log(result);
} catch (e) {
	console.log(e);
}

2.oss-axios

1.signature、policy、callback

// 当前环境为 NodeJS 环境,实际生产环境中注意选择合适插件;
const crypto = require('crypto');
const { Buffer } = require("buffer");
const { Base64 } = require('js-base64');

const accesskey = "accesskey";
// 10分钟后过期
const timestamp = Date.now() + 10 * 60 * 1000;

const policyText = {
	// 设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件
  	"expiration": `${new Date(timestamp).toISOString()}`, 
  	"conditions": [
    	// 设置上传文件的大小限制
    	["content-length-range", 0, 1024 * 1024 * 2] 
  ]
};

const callbackJSON = {
  	// 服务端回调接口地址
  	callbackUrl: 'callbackUrl',
  	// 所需返回的文件信息配置
	callbackBody:
	"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
  	callbackBodyType: "application/x-www-form-urlencoded",
}

const policy = Base64.encode(JSON.stringify(policyText));
const signature = crypto.createHmac("sha1", accesskey)
  .update(policyBase64)
  .digest()
  .toString("base64");
const callback = Buffer.from(JSON.stringify(callbackJSON)).toString("base64");

2.axios-request

function fileCreate (file) {
	const uploadData = new FormData();
	uploadData.append("OSSAccessKeyId", 'OSSAccessKeyId');
	uploadData.append("key", 'application/${filename}');
	uploadData.append("policy", "policy");
	uploadData.append("success_action_status", 200);
	// uploadData.append("callback", "callback");
	uploadData.append("name", file.name);
	uploadData.append("Signature", "Signature");
	uploadData.append("file", file);

	return uploadData;
}

const uploadData = fileCreate (file);

axios({
  	// 您的OSS访问域名,格式为BucketName.Endpoint,例如 post-test.oss-cn-hangzhou.aliyuncs.com;
  	url: 'http://post-test.oss-cn-hangzhou.aliyuncs.com',
  	method: 'post',
 	data: uploadData,
  	headers: { 'Content-Type': 'multipart/form-data' }
}).then(r => console.log(r));

3.oss-wx.uploadFile

// 通过 wx.chooseImage 函数获取到返回值
const tempFilePaths = res.tempFilePaths;

wx.uploadFile({
  	// 您的OSS访问域名,格式为BucketName.Endpoint,例如 post-test.oss-cn-hangzhou.aliyuncs.com;
  	url: 'http://post-test.oss-cn-hangzhou.aliyuncs.com',
  	filePath: tempFilePaths[0],
  	name: 'file',
  	formData: {
	    name: tempFilePaths[0],
	    key: 'application/${filename}',
	    policy: policy,
	    OSSAccessKeyId: OSSAccessKeyId,
	    signature: signature,
	    success_action_status: '200',
	    callback: OSSCallback,
  	},
  	success(res) {
    	//do something
    	if (200 === res.statusCode) console.log(res);
  	},
});
 类似资料: