前端(react)上传到阿里云OSS存储

需求背景

由于现有的后台管理系统,上传的视频越来越大,加上上传视频较慢,后端小哥提出直接从前端上传视频或者其他文件到阿里云OSS存储。

  • 阿里云OSS

阿里云OSS文档介绍,这里不做过多赘述

安装

原本在最开始的时候,是使用node版本的SDK,最开始使用的[nodejs版本]

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
async function put() {
try {
let result = await client.put('qq.mp4', fileObj);
console.log(result);
} catch (err) {
console.log(keyObject.AccessKeyId);
console.log(keyObject.AccessKeySecret);
console.log(keyObject.SecurityToken);

console.log(err);
}
}
put();

开始上传图片的时候还没有翻车,但是上传超过30多M的时候,就翻车了,在阿里云OSS后台查看文件大小为0KB

本来是想用fs模块来操作文件的,但是发现fs在浏览器端,没法儿使用所以就放弃了nodejs版本的SDK

browser版本

后面仔细查阅文档, 发现browser版本SDK有一个片段上传的文档,于是就采用了[browser]版本。

使用 browser版本的SDK支持片段上传,同时可以通过片段上传返回回来的进度,制作进度条提示,方便操作业务逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let ossConfig = {
region: 'oss-cn-hangzhou',
//云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,部署在服务端使用RAM子账号或STS,部署在客户端使用STS。
accessKeyId: keyObject.AccessKeyId,
accessKeySecret: keyObject.AccessKeySecret,
stsToken: keyObject.SecurityToken,
bucket: 'wesmart-app'
}

let tempCheckpoint;

// 定义上传方法。
async function multipartUpload() {
try {
// object-key可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
let result = await client.multipartUpload('02', fileObj, {
progress: function (p, checkpoint) {
// 断点记录点。浏览器重启后无法直接继续上传,您需要手动触发上传操作。
tempCheckpoint = checkpoint;
console.log(p);
console.log(checkpoint);
},
mime: 'video/mp4'
})
} catch (e) {
console.log(e);
}
}
  • client.multipartUpload方法
  1. 第一个参数为自定义的上传文件的名称,建议使用时间戳进行后缀命名,保证文件的唯一性,不会被覆盖

  2. 第二个参数为文件 回调函数progress,可以查看上传的进度以及文件的相关信息

注意事项

上面需要的对象字段可以通过阿里云后台OSS进行查看,在开发的过程中,个人建议通过请求后端返回的相关key值进行操作

在上传代码的时候,使用的put请求,而且刚开始会报错跨域的问题,需要在阿里云OSS进行配置允许请求

1
Exresponse Header设置为etag

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import React, { useState, useEffect } from 'react';
import axios from "axios";
const OSS = require('ali-oss');
class Example extends React.Component {
state = {
count: 0,
keyObject: {},
upfile: "",
}
componentDidMount() {
this.getData();
}
getData() {
let that = this;
axios.get('获取keyId的接口地址')
.then(function (response) {
console.log(response);
let { status, data } = response;
if (status == 200) {
that.setState({
keyObject: data
});
}
})
.catch(function (error) {
console.log(error);
});
}

handleUpload() {
let { keyObject, upfile } = this.state;
var fileObj = document.getElementById("file").files[0];
console.log(fileObj);
console.log(keyObject);
let ossConfig = {
region: 'oss-cn-hangzhou',
//云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,部署在服务端使用RAM子账号或STS,部署在客户端使用STS。
accessKeyId: keyObject.AccessKeyId,
accessKeySecret: keyObject.AccessKeySecret,
stsToken: keyObject.SecurityToken,
bucket: 'wesmart-app'
}
let client = new OSS({
region: 'oss-cn-hangzhou',
//云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,部署在服务端使用RAM子账号或STS,部署在客户端使用STS。
accessKeyId: keyObject.AccessKeyId,
accessKeySecret: keyObject.AccessKeySecret,
stsToken: keyObject.SecurityToken,
bucket: 'wesmart-app'
});

// async function put() {
// try {
// let result = await client.put('qq.mp4', fileObj);
// console.log(result);
// } catch (err) {
// console.log(keyObject.AccessKeyId);
// console.log(keyObject.AccessKeySecret);
// console.log(keyObject.SecurityToken);

// console.log(err);
// }
// }

// put();


let tempCheckpoint;

// 定义上传方法。
async function multipartUpload() {
try {
// object-key可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
let result = await client.multipartUpload('02', fileObj, {
progress: function (p, checkpoint) {
// 断点记录点。浏览器重启后无法直接继续上传,您需要手动触发上传操作。
tempCheckpoint = checkpoint;
console.log(p);
console.log(checkpoint);
},
mime: 'video/mp4'
})
} catch (e) {
console.log(e);
}
}

// 开始分片上传。
multipartUpload();

// 暂停分片上传。
client.cancel();

// 恢复上传。
let resumeclient = new OSS(ossConfig);
async function resumeUpload() {
try {
let result = await resumeclient.multipartUpload('02', fileObj, {
progress: function (p, checkpoint) {
tempCheckpoint = checkpoint;
console.log(p);
console.log(checkpoint);
},
checkpoint: tempCheckpoint,
mime: 'video/mp4'
})
} catch (e) {
console.log(e);
}
}
resumeUpload();
}

handleChange(e) {
e.persist();
this.setState({ upfile: e.target.value });
}

render() {
const { upfile } = this.state;
return (
<div>
<script type="text/javascript" src="http://gosspublic.alicdn.com/aliyun-oss-sdk-x.x.x.min.js"></script>
<p><input id="file" type="file" onChange={this.handleChange.bind(this)} value={upfile} /></p>
<button onClick={this.handleUpload.bind(this)}>
上传
</button>
</div>
)
}

}

export default Example;