什么是OSS?
阿里云对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
安装
- 通过
CDN
引入
<!-- 引入在线资源 -->
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-4.4.4.min.js"></script>
- 通过
npm
安装
$ npm install ali-oss -S
注意:使用npm
引入时,需要在使用的位置引入OSS
let OSS = require('ali-oss');
初始化OSS
const config = {
accessKeyId: 'your access key',
accessKeySecret: 'your access secret',
stsToken: '使用临时授权方式',
endpoint: 'OSS域名',
bucket: 'your bucket name',
secure: true // true 使用 HTTPS, false 使用 HTTP
}
const client = new OSS.Wrapper(config)
if (!client) {
alert('OSS 初始化失败,无法上传!')
return
}
以上配置参数,需由后端提供。
为了安全性,accessKeyId 和 accessKeySecret 不存储于前端。且需要 stsToken 临时 token 授权。
简单上传
// 支持File对象、Blob数据以及OSS Buffer。
const data = '<File Object>';
// or const data = new Blob('content');
// or const data = new OSS.Buffer('content'));
async function putObject () {
try {
// object-key可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。
let result = await client.put('object-key', data);
console.log(result);
} catch (e) {
console.log(e);
}
}
putObject();
分片上传
大文件可采用分片上传,并且能够获取到上传进度。
const tempCheckpoint = {} // 分片续传的位置
multipartUpload(tempCheckpoint)
async function multipartUpload(tempCheckpoint) {
try {
const results = await client.multipartUpload(fileName, file, {
progress: (percentage, checkpoint) => {
tempCheckpoint = checkpoint // 断点位置
if (tempCheckpoint) { // 未传完,则继续上传
multipartUpload(tempCheckpoint)
}
progressCallback && progressCallback(percentage) // 进度的回调函数
},
checkpoint: tempCheckpoint
})
uploadResponse(results) // 上传完成
} catch (e) {
console.log(e)
}
}
// 上传返回
function uploadResponse(results) {
let fileUrl = ''
if (results.url) {
fileUrl = results.url
callback && callback(fileUrl) // 成功回调
} else if (results.res.requestUrls) {
const result = results.res.requestUrls
if (result[0].indexOf('?') !== -1) {
fileUrl = result[0].slice(0, result[0].indexOf('?'))
} else {
fileUrl = result[0]
}
callback && callback(fileUrl) // 成功回调
} else {
Vue.$message.error('上传失败')
}
}
完整代码如下
import Vue from 'vue'
import moment from 'moment'
import md5 from 'md5'
import { getStsTokenAPI } from '@/api/upload'
/**
* @description: 上传文件至 OSS
* @param {*} type 获取 OSS 文件前缀
* @param {*} file 需要上传的文件
* @param {*} progressCallback 进度的回调函数
* @param {*} callback 上传成功的回调函数
*/
const uploadFileToServer = (type, file, progressCallback, callback) => {
getStsTokenAPI({ type })
.then(res => {
// eslint-disable-next-line
const config = {
accessKeyId: res.data.AccessKeyId,
accessKeySecret: res.data.AccessKeySecret,
stsToken: res.data.SecurityToken,
endpoint: 'https://' + res.data.endpoint,
bucket: res.data.bucket,
secure: true
}
const client = new OSS.Wrapper(config)
if (!client) {
Vue.$message.error('OSS 初始化失败,无法上传!')
return
}
const name = md5(file.name + moment().valueOf()) + getSuffix(file.name) // 文件名
const catalog = res.data.upload_type_prefix // 目录
const fileName = catalog + name
// 图片整传
if (type === 10) {
client.multipartUpload(fileName, file)
.then(results => {
uploadResponse(results)
})
} else { // 如果是音频和视频采用断点续传
const tempCheckpoint = {} // 分片续传的位置
multipartUpload(tempCheckpoint)
async function multipartUpload(tempCheckpoint) {
try {
const results = await client.multipartUpload(fileName, file, {
progress: (percentage, checkpoint) => {
console.log(percentage)
tempCheckpoint = checkpoint
if (tempCheckpoint) {
multipartUpload(tempCheckpoint)
}
progressCallback && progressCallback(percentage) // 进度的回调函数
},
checkpoint: tempCheckpoint
})
uploadResponse(results)
} catch (e) {
console.log(e)
}
}
}
// 上传返回
function uploadResponse(results) {
let fileUrl = ''
if (results.url) {
fileUrl = results.url
callback && callback(fileUrl) // 成功回调
} else if (results.res.requestUrls) {
const result = results.res.requestUrls
if (result[0].indexOf('?') !== -1) {
fileUrl = result[0].slice(0, result[0].indexOf('?'))
} else {
fileUrl = result[0]
}
callback && callback(fileUrl) // 成功回调
} else {
Vue.$message.error('上传失败')
}
}
})
}
/**
* @description: 获取文件后缀名
* @param {String} 文件名
*/
function getSuffix(filename) {
const pos = filename.lastIndexOf('.')
let suffix = ''
if (pos !== -1) {
suffix = filename.substring(pos)
}
return suffix
}
export default uploadFileToServer