elementUi+vue+七牛云如何上传文件和视频( 支持断点续传)
前提
七牛云上传当然必须保证token的有效,所有我们需要编写后端服务来实现token
获取,这里简单展示一下代码
- 配置
env
QINIU_SK=A**********0QWp
QINIU_AK=uLP4c******J0BXi5P
QINIU_BUKET_PATH=my-image
QINIU_HOST=http://cdn.surest.cn/
QINIU_UPLOAD_URL=https://upload-z2.qiniup.com
QINIU_PREFIX=webvideo
以上的配置应该很清楚,可以自定义一些自己用的到的参数进去
AK、SK 必须
BUKET 对应着你的空间,就是云存储进去单空间管理里面,
host 对应着你的cdn域名,这里的域名是我解析过后的
QINIU_UPLOAD_URL 对应上传地址
存储区域 区域代码 客户端上传地址 服务端上传地址
华东 ECN http(s)://upload.qiniup.com http(s)://up.qiniup.com
华北 NCN http(s)://upload-z1.qiniup.com http(s)://up-z1.qiniup.com
华南 SCN http(s)://upload-z2.qiniup.com http(s)://up-z2.qiniup.com
北美 NA http(s)://upload-na0.qiniup.com http(s)://up-na0.qiniup.com
东南亚 http(s)://upload-as0.qiniup.com http(s)://up-as0.qiniup.com
代码编写
因为前端可能多个地方调用我们的api,我们可以对他针对性的封装
Route::group(['prefix' => 'upload'], function () {
Route::get('/qiniu/sign', 'QiniuController@uploadSign'); # 获取七牛云密钥
});
> 安装composer 包
> composer require qiniu/php-sdk -vvv
use Qiniu\Auth;
class QiniuController extends Controller
{
/**
* 获取七牛云密钥
* User: surest
* Date: 2020/6/1
*/
public function uploadSign()
{
// 用于签名的公钥和私钥
$accessKey = env('QINIU_AK');
$secretKey = env('QINIU_SK');
$auth = new Auth($accessKey, $secretKey);
$token = $auth->uploadToken(env('QINIU_BUKET_PATH'));
$host = env('QINIU_HOST');
$buket = env('QINIU_BUKET_PATH');
$uploadUrl = env('QINIU_UPLOAD_URL');
return $this->success(compact('token', 'host', 'buket', 'uploadUrl'));
}
}
单文件上传
这里针对前端组件进行封装
> 创建一个vue mixin
> mkdir -p ./src/layout/mixin/UploadHandler.js
// 这里是封装的一个请求后端方法
import { getToken } from "@/api/qiniu";
export default {
data(){
return {
qiniuToken: null,
host: null,
buket: null,
uploadUrl: null
}
},
methods: {
getToken(){
// 这里返回一个 Promise
return new Promise((resolve, reject) => {
getToken().then(response => {
this.qiniuToken = response.data.token
this.host = response.data.host
this.buket = response.data.buket
this.uploadUrl = response.data.uploadUrl
console.log(response.data)
resolve()
})
})
}
}
};
使用
<template>
<el-upload
style="float:left"
:action="importApi"
:on-success="uploadDocSuccess"
:on-error="uploadError"
:data="postData"
:show-file-list="false"
>
<el-button size="mini" type="success">培训文档上传</el-button>
</el-upload>
</template>
> 导入
import UploadMixin from '@/layout/mixin/UploadHandler'
export default {
...
mixins: [UploadMixin],
data(){
return {
postData: {
token: null
},
importApi: null
....
}
},
methods: {
....
/**
* 合同导入成功
*/
uploadSuccess(response) {
this.excelLoading = false;
Message.success("导入成功");
Message.success(this.host + response.key) // 输出的就是文件地址
},
uploadError(err) {
let msg = JSON.parse(err.message);
console.log(msg)
msg = msg.message;
Message.error("导入失败: " + msg);
this.excelLoading = false;
},
/**
* 初始化导入七牛云参数
*/
initImport() {
this.getToken().then(() => {
this.importApi = this.uploadUrl
this.postData.token = this.qiniuToken
})
},
...
}
}
视频上传
直接贴代码
<template>
<div class="upload">
<div id="video_container">
<div id="pickfiles"><el-button style="margin-top: 5px" type="primary">上传视频</el-button></div>
<div>
<div class="upload_info">
<b>共{{ fileSize }}MB | 已上传{{ fileLoaded }} | 上传速度{{ fileSpeed }}/s</b>
</div>
<div>
<b>上传进度:{{ filePercent }}%</b>
</div>
</div>
</div>
<div class="cover-pic" v-if='coverPic'>
<img :src="coverPic" alt="">
</div>
</div>
</template>
<script>
import { getToken, chttp } from '@/api/qiniu'
require('qiniu-js/dist/qiniu.min.js')
import * as qiniu from 'qiniu-js'
export default {
data () {
return {
fileSize: 0,
fileLoaded: 0,
fileSpeed: 0,
filePercent: 0,
uploader: null,
token: '',
filename: '',
hash: '',
resFileName: '',
coverPic: '',
phoneType: null,
domain: undefined,
buket: undefined
}
},
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
},
init() {
this.data = this.$data
},
initUploader () {
let plupload = window.plupload
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: _this.buket, // 空间名
unique_names: false, // 默认false,key为文件名。若开启该选项,JS-SDK会为每个文件自动生成key(文件名)
save_key: false, // 默认false。若在服务端生成uptoken的上传策略中指定了sava_key,则开启,SDK在前端将不对key进行任何处理
domain: _this.domain, // 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)
console.log(response)
let coverPic = _this.domain + response.key
_this.$emit('toHtml', coverPic)
console.log(response, coverPic)
},
Error: function (up, err, errTip) {
// 上传出错时,处理相关的事情
console.log(arguments)
},
UploadComplete: function () {
// 队列文件处理完毕后,处理相关的事情
console.log(arguments)
}
}
})
console.log(this.uploader)
},
getToken (callback) {
getToken().then(res => {
this.token = res.data.token
this.domain = res.data.host
this.buket = res.data.buket
console.log(res.data)
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
},
uploadFile() {
}
},
mounted () {
this.phoneType = this.getPhoneType()
this.filename = 'webvideo/' + new Date().getTime() + '.mp4'
// this.initUploader()
this.getToken(() => {
console.log(this)
this.initUploader()
})
},
}
</script>
<style lang="scss" scoped>
</style>
使用
import QiniuUpload from "@/components/Upload/Qiniu"
export default {
...
components: { QiniuUpload }
}
本文由 邓尘锋 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Mar 22, 2021 at 04:46 pm