七牛云上传文件
七牛云上传文件
七牛云上传文件
七牛云上传文件
客户端:react: ^17.0.2,antd: “^4.20.1
服务端:egg: ^2.15.1,qiniu: ^7.8.0”�
客户端
1:获取上传凭证�(token)
2:文件上传
- 直接上传七牛云
- 通过服务端封装的上传接口上传(可通过
antd的customRequest自定义上传)
这里我用第一种方式:通过 antd 的 Upload 组件上传,这里需要注意 存储区域
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
const UploadIProps: UploadProps = {
name: 'file',
fileList: [],
action: 'http://up-cn-east-2.qiniup.com',
data: {
key: filename,
token: token
},
beforeUpload: async (file) => {
await getUploadToken(file); // 这里是从服务端拿上传凭证
},
onChange: async (info) => {
if (info.file.status === 'done') {
setPrivateUrl([]);
await getFileList();
message.success('uploaded successfully');
} else if (info.file.status === 'error') {
message.error('upload failed');
}
}
};
const App: React.FC = () => (
<Upload {...UploadIProps}>
<Button icon={<UploadOutlined />}>Click to Upload</Button>
</Upload>
);
注意!!! 上传的时候,如果遇到类似400:incorrect region, please use xxx.qiniu.com的错误,说明是上传域名和空间所在的区域不匹配,多发生在旧的sdk、工具和插件上。后面的 xxx.qiniu.com是正确的上传域名。 存储区域和上传域名的对应关系见https://developer.qiniu.com/kodo/manual/1671/region-endpoint
服务端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 获取上传token
async getToken() {
const { ctx, app: { config: { qiNiu: { bucket, accessKey, secretKey } } } } = this;
try {
const mac = new QN.auth.digest.Mac(accessKey, secretKey);
const options = {
scope: bucket,
expires: 60 * 60,
fsizeLimit: 1024 * 1024, // 限定上传文件大小最大值,单位Byte(这里1MB)
mimeLimit: 'image/*', // 限定用户上传的文件类型
};
const putPolicy = new QN.rs.PutPolicy(options);
const uploadToken = putPolicy.uploadToken(mac);
ctx.Success('添加成功', uploadToken);
} catch (e) {
ctx.Fail('获取token失败');
}
}
扩展
获取指定前缀的文件列表 - 私有空间
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
// 获取指定前缀的文件列表 - 私有空间
async getFileList() {
const { ctx } = this;
const { data, msg, success } = await this.getPrefixList();
if (!success) {
return ctx.Fail(msg);
}
ctx.Success('success', data);
}
getPrefixList() {
return new Promise(resolve => {
const { ctx, app: { config: { qiNiu: { bucket, accessKey, secretKey } } } } = this;
const { limit, prefix, marker } = ctx.params;
const mac = new QN.auth.digest.Mac(accessKey, secretKey);
const config = new QN.conf.Config();
// config.useHttpsDomain = true;
config.zone = QN.zone.Zone_z0;
const bucketManager = new QN.rs.BucketManager(mac, config);
const privateBucketDomain = 'http://rs6aoe3h8.bkt.clouddn.com';
const deadline = parseInt(Date.now() / 1000) + 3600; // 1小时过期
const options = {
limit,
marker,
prefix,
};
try {
bucketManager.listPrefix(bucket, options, (err, respBody, respInfo) => {
if (err) {
throw err;
}
if (respInfo.statusCode === 200) {
// 如果这个nextMarker不为空,那么还有未列举完毕的文件列表,下次调用listPrefix的时候,
// 指定options里面的marker为这个值
const nextMarker = respBody.marker;
const items = respBody.items;
const obj = {
nextMarker: nextMarker ? nextMarker : '',
privateDownloadUrl: [],
};
items.forEach(function(item) {
const privateDownloadUrl = bucketManager.privateDownloadUrl(privateBucketDomain, item.key, deadline);
obj.privateDownloadUrl.push(privateDownloadUrl);
});
resolve({ data: obj, success: true });
} else {
resolve({ msg: respInfo, success: false });
}
});
} catch (e) {
resolve({ msg: e, success: false });
}
});
}
本文由作者按照 CC BY 4.0 进行授权