Qiniu-JavaScript-SDK基于七牛云存储官方 API 构建,其中上传功能基于 H5 File API。开发者基于 JS-SDK 可以方便的从浏览器端上传文件至七牛云存储,并对上传成功后的文件进行丰富的数据处理操作。
我用的是qiniu-js的1.x版本,可以到文档里详细看看
安装引入
// 下载qiniu-js
npm install qiniu-js@1.X -D
// 在页面中引入
import * as qiniu from 'qiniu-js'
功能简介
上传
- html5 模式大于 4 M 时可分块上传,小于 4 M 时直传
- Flash、html4 模式直接上传
- 继承了 Plupload 的功能,可筛选文件上传、拖曳上传等
服务端准备
JS-SDK依赖服务端颁发的上传凭证,后端服务应提供一个 URL 地址,供 SDK 初始化使用,前端通过 Ajax 请求该地址后获得 upToken。 Ajax 请求成功后,服务端应返回如下格式的 json:
{
"uptoken": "0MLvWPnyya1WtPnXFy9KLyGHyFPNdZceomL..."
}
上传步骤
1.生成上传选择的点选按钮
<div id="video_container" class="video-container">// 上传按钮的父元素
<div id="pickfiles" class="pickfiles"></div>// 上传按钮
</div>
2.前端通过接口请求获取token信息
3.创建Qiniu.uploader
this.uploader = Qiniu.uploader({
...
})
// uploader为一个plupload对象,继承了所有plupload的方法
常用配置
- 上传选择的点选按钮,这是必须项
browse_button: 'pickfiles'
- 上传区域的设置
container: 'video_container' // 上传区域的DOM Id
- 存储空间的空间名 七牛云后台可查
bucket_name: 'bucket01'
- 空间域名 七牛云后台可查
domain: 'https://xxx.com'
- 上传凭证,JS-SDK 依赖服务端颁发 token,必填项
token: 'xxxxxxx'
- 分片上传时,每块的体积
七牛云分片上传文档:https://developer.qiniu.com/k...
chunk_size: '4mb'
- 文件类型的筛选
~~filters: { // 这个属性实测只在电脑上有用
mime_types: [
{ title: 'Video files', extensions: 'avi,mov,rmvb,rm,flv,mp4,3GP,asf,qt,mpeg,mpg,dat,ram,viv' },
{ title: 'Image files', extensions: 'png' }
]~~
// 筛选文件类型可以放到BeforeUpload中处理
// return false 阻断文件上传
init: {
BeforeUpload: function (up, file) {
_this.fileType = file.type.split('/')[0]
if (_this.fileType !== 'video') {
_this.$toast('请上传视频文件')
return false
}
}
}
- 最大文件体积限制
max_file_size: '100mb',
init: {
Error: function (up, err, errTip) {
// 上传出错时,处理相关的事情
if (err.message === 'File size error.') {
// 当文件大小超过限制 走这里
}
}
}
- 获取上传文件成功后通过FileUploaded拿到key,拼上域名就是文件的URL,想要获取文件的封面图、元信息等可以到七牛文档查阅,https://developer.qiniu.com/d... eg: domain + key + '?vframe/png/offset/7/w/480/h/360'
init: {
FileUploaded: function (up, file, info) {
console.log('FileUploaded')
let response = JSON.parse(info.response)
_this.hash = response.hash
_this.resFileName = response.key
_this.coverPic = 'https://xxx.com/' + response.key + '?vframe/png/offset/7/w/480'
}
}
- 获取上传文件的进度
init: {
UploadProgress: function (up, file) {
// 每个文件上传时,处理相关的事情
_this.filePercent = parseInt(file.percent)
}
}
遇到的坑
在项目工作过程中遇到了一个问题,iphone5的手机可以选择视频但上传七牛进度一直是1%,
这个问题原因应该是之前plupload一直没有彻底解决的iOS环境下兼容性的问题,经过多次尝试找到解决办法,添加下面这个属性就可以解决
multi_selection: false, // 限制只能上传单张图片
但是添加这个属性后选择视频会多走一层预览+压缩的步骤,这个步骤过于耗时,所以做了特殊处理,只有在iphone5时才将multi_selection置为false,这样虽然损失了一些便利性,但确保了上传视频功能的正常使用
多个上传实例
var option1 = {
key : val,
……
};
var uploader = Qiniu.uploader(option1);
var Qiniu2 = new QiniuJsSDK(); // QiniuJsSDK顾名思义七牛的JS-SDK对象
var option2 = {
key : val,
……
};
var uploader2 = Qiniu2.uploader(option2);
完整代码
<template>
<div class="upload">
<div id="video_container">
<div id="pickfiles">上传视频</div>
<div>
<div class="upload_info">
<b>共{{ fileSize }}MB | 已上传{{ fileLoaded }} | 上传速度{{ fileSpeed }}/s</b>
</div>
<div>
<b>上传进度:{{ filePercent }}%</b>
</div>
<button @click="pauseUpload">暂停上传</button>
<button @click="continueUpload">继续上传</button>
</div>
</div>
<div class="cover-pic" v-if='coverPic'>
<img :src="coverPic" alt="">
</div>
</div>
</template>
<script>
import { apis, chttp } from '@/libs/interfaces'
require('qiniu-js/dist/qiniu.min.js')
export default {
data () {
return {
fileSize: 0,
fileLoaded: 0,
fileSpeed: 0,
filePercent: 0,
uploader: null,
token: '',
filename: '',
hash: '',
resFileName: '',
coverPic: '',
phoneType: null
}
},
methods: {
pauseUpload () {
this.uploader.stop()
},
continueUpload () {
this.uploader.start()
},
toDecimal (size) {
size = size / 1024 / 1024
var f = parseFloat(size)
if (isNaN(f)) {
return
}
f = Math.round(size * 10) / 10
var s = f.toString()
var rs = s.indexOf('.')
if (rs < 0) {
rs = s.length
s += '.'
}
while (s.length <= rs + 1) {
s += '0'
}
return s
},
initUploader () {
let plupload = window.plupload
let Qiniu = global.Qiniu
let _this = this
// domain为七牛空间对应的域名,选择某个空间后,可通过 空间设置->基本设置->域名设置 查看获取
let isIphone5 = this.phoneType === '5'
// uploader为一个plupload对象,继承了所有plupload的方法
this.uploader = Qiniu.uploader({
runtimes: 'html5,flash,html4', // 上传模式,依次退化
browse_button: 'pickfiles', // 上传选择的点选按钮,必需
uptoken: this.token, // uptoken是上传凭证,由其他程序生成
get_new_uptoken: true, // 设置上传文件的时候是否每次都重新获取新的uptoken
bucket_name: 'common-web', // 空间名
unique_names: false, // 默认false,key为文件名。若开启该选项,JS-SDK会为每个文件自动生成key(文件名)
save_key: false, // 默认false。若在服务端生成uptoken的上传策略中指定了sava_key,则开启,SDK在前端将不对key进行任何处理
domain: 'https://xxx.com', // bucket domain eg:http://qiniu-plupload.qiniudn.com/
container: 'video_container', // 上传区域DOM ID,默认是browser_button的父元素
max_file_size: '10mb', // 最大文件体积限制
dragdrop: false, // 开启可拖曳上传
drop_element: 'video_container', // 拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传
chunk_size: '4mb', // 分块上传时,每块的体积
max_retries: 3, // 上传失败最大重试次数
auto_start: true, // 选择文件后自动上传,若关闭需要自己绑定事件触发上传
multi_selection: !isIphone5,
init: {
Key: function (up, files) {
return _this.filename
},
FilesAdded: function (up, files) {
plupload.each(files, function (file) {
// 文件添加进队列后,处理相关的事情
console.log('FilesAdded')
_this.fileSize = _this.toDecimal(file.size)
})
},
BeforeUpload: function (up, file) {
console.log('BeforeUpload')
},
ChunkUploaded: function (up, file, info) {
console.log('ChunkUploaded')
},
UploadProgress: function (up, file) {
// 每个文件上传时,处理相关的事情
_this.filePercent = parseInt(file.percent)
_this.fileLoaded = plupload.formatSize(file.loaded).toUpperCase()
_this.fileSpeed = plupload.formatSize(file.speed).toUpperCase()
},
FileUploaded: function (up, file, info) {
console.log('FileUploaded')
let response = JSON.parse(info.response)
_this.hash = response.hash
_this.resFileName = response.key
_this.coverPic = 'https://xxx.com/' + response.key + '?vframe/png/offset/7/w/480'
},
Error: function (up, err, errTip) {
// 上传出错时,处理相关的事情
_this.$toast('Error =')
_this.$toast(err)
_this.$toast('errTip =')
_this.$toast(errTip)
},
UploadComplete: function () {
// 队列文件处理完毕后,处理相关的事情
_this.$toast('UploadComplete')
}
}
})
},
getToken (callback) {
this.filename = 'webvideo/' + new Date().getTime() + '.mp4'
let params = {
filename: this.filename
}
chttp.get(apis.qiniuToken, { params: params })
.then(res => {
this.token = res.token
callback()
})
},
getPhoneType () {
// 正则,忽略大小写
var patternPhone = new RegExp('iphone', 'i')
var patternAndroid = new RegExp('Android', 'i')
var userAgent = navigator.userAgent.toLowerCase()
var isAndroid = patternAndroid.test(userAgent)
var isIphone = patternPhone.test(userAgent)
var phoneType = 'phoneType'
if (isAndroid) {
var zhCnIndex = userAgent.indexOf('-')
var spaceIndex = userAgent.indexOf('build', zhCnIndex + 4)
var fullResult = userAgent.substring(zhCnIndex, spaceIndex)
phoneType = fullResult.split('')[1]
} else if (isIphone) {
// 6 w=375 6plus w=414 5s w=320 5 w=320
var wigth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
if (wigth > 400) {
phoneType = 'iphone6 plus'
} else if (wigth > 370) {
phoneType = 'iphone6'
} else if (wigth > 315) {
phoneType = '5'
} else {
phoneType = 'iphone 4s'
}
} else {
phoneType = '您的设备太先进了'
}
return phoneType
}
},
mounted () {
this.phoneType = this.getPhoneType()
this.getToken(() => {
this.initUploader()
})
}
}
</script>
<style lang="scss" scoped>
</style>
JS-SDK文档:https://developer.qiniu.com/k...
plupload官网:https://www.plupload.com/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。