安装:
cropperjs : https://github.com/fengyuanchen/cropperjs
npm install cropperjs --save --save-exact
--save : 成功后存到 package.json 中 dependencies 中
--save-exact : 精确版本号(精确指定版本)
Qiniu-JavaScript-SDK : https://developer.qiniu.com/kodo/1283/javascript
npm install qiniu-js --save --save-exact
或
package.json 中 dependencies 参数设置
"dependencies": {
"axios": "0.24.0",
"cropperjs": "1.5.12",
"qiniu-js": "3.4.0",
"vant": "^2.8.1",
"vue": "^2.5.2",
"vue-axios": "3.4.0",
"vue-router": "^3.0.1"
},
执行 npm install
qiniuUpfile.js(上传时显示上传百分比)
import * as qiniu from 'qiniu-js'
import { Toast } from 'vant';
/*
* 将 base64 图片编码转为 Blob 对象
* @dataURI 图片 base64 编码
* @returns {Blob}
*/
const dataURItoBlob = (dataURI) => {
let byteString = atob(dataURI.split(',')[1]);
let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
let ab = new ArrayBuffer(byteString.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], {
type: mimeString
});
}
export default function(file , token , fileType) {
if (typeof(file) === 'string') {
file = dataURItoBlob(file);
}
return new Promise((resolve, reject) => {
const observable = qiniu.upload(
file, //file
'file_' + Math.floor(Math.random() * 1000000000) + '_' + new Date().getTime(), //key
token, //token
//putExtra
{
// fname: file.name,
// fname: 'file_',
// mimeType: [] || null,
// mimeType: ["image/png", "image/jpeg", "image/gif", 'video/mp4', 'video/mov', 'video/avi', 'video/flv', 'video/mkv', 'video/rmvb', 'video/quicktime'],
mimeType: fileType ? fileType : null, // "image/jpg" or "video/mp4" or "text/plain" ...
},
//config
{
useCdnDomain: true, // cdn
unique_names: false, // 唯一名称
region: qiniu.region.z0 // 根据区域设置上传的域名
},
);
const subscription = observable.subscribe({
next(res) {
// console.log(res);
Toast.loading({
duration: 0,
message: '上传' + parseInt(res.total.percent) + '%',
forbidClick: true,
})
},
error(err) {
Toast.clear();
console.log(err);
reject(err);
},
complete(res) {
Toast.clear();
// console.log(res);
resolve(res);
}
})
});
}
上传图片页面 uploadPicTest.vue
七牛初始化参数数据接口获取
...
this.token = res.data.token;
this.domain = res.data.domain;
...
<template>
<div>
<!-- 上传图片 -->
<div style="width: 100%;height: 642px;position: relative;">
<div style="width: 6px; height: 100px; background-color: #eee; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);"></div>
<div style="width: 100px; height: 6px; background-color: #eee; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);"></div>
<!-- 结果图片 : 上传七牛云后的图片 -->
<img v-if="image" :src="image" style="width: 100%;position: relative;" />
<!-- 上传图片控件 -->
<input ref="referenceUpload" @change="sendImg" type="file" accept="image/*" style="width: 100%; height: 100%; position: absolute; left: 0; top: 0; opacity: 0;" />
</div>
<!-- 编辑上传的图片 -->
<div v-show="magage" class="pop">
<div class="pop_body">
<div class="showimg">
<!-- 需要编辑的图片 : 上传的图片处理后的base64格式 -->
<img v-if="magageImg" :src="magageImg" id="image" />
</div>
<div>
<div @click="magage = false" class="base_btn">取消</div>
<!-- 编辑图片-旋转图片 : 苹果手机如果处理的是相机拍照的图片且较大,则旋转后上传图片失败(空白的图片) -->
<!-- <div @click="rotateImg" class="base_btn">旋转图片</div> -->
<div @click="saveImg" class="base_btn">确定</div>
</div>
</div>
</div>
<!-- 上传文件 -->
<div class="upfile_controls">
<div style="width: 6px; height: 100px; background-color: #eee; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);"></div>
<div style="width: 100px; height: 6px; background-color: #eee; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);"></div>
<img v-if="url && filetype == 'img'" :src="url" />
<img v-if="url && filetype == 'pdf'" src="../assets/img/pdf.png" />
<input ref="referenceUploadFile" @change="sendFile" type="file" />
</div>
<!-- 上传视频 -->
<div class="upfile_controls" style="width: 400px; height: 300px;">
<div style="width: 6px; height: 100px; background-color: #eee; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);"></div>
<div style="width: 100px; height: 6px; background-color: #eee; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);"></div>
<video v-if="upvideo" id="videoID" controls :src="upvideo" @canplaythrough="getVideoTime($event)" preload="auto" x-webkit-airplay="true" webkit-playsinline="true" playsinline="true" x5-playsinline="true"></video>
<!-- 视频-上传input -->
<input v-show="!upvideo" ref="referenceUploadVideo" @change="sendVideo" type="file" accept="video/*" />
</div>
</div>
</template>
<script>
import { configQiNui } from '@/api/api.js';
import 'cropperjs/dist/cropper.css';
import Cropper from 'cropperjs';
import qiniuUpFile from '@/api/qiniuUpfile.js';
export default {
name: 'Test',
data() {
return {
// 七牛初始化数据
token : '',
domain : '',
/*************************/
// 上传图片
image:'',
magage:false, // 显示编辑界面
magageImg:'', //需要编辑的图片 : 上传的图片处理后的base64格式
cropper:null,
/*************************/
// 上传文件
url:'',
filetype:'',
/*************************/
// 上传视频
upvideo:''
}
},
created() {
// 获取七牛初始化数据接口
configQiNui().then(res=>{
console.log(res);
this.token = res.data.token;
this.domain = res.data.domain;
}).catch(err=>{
console.log(err);
})
},
mounted() {
},
watch: {
},
methods: {
// 上传base64编码图片到七牛云
// putb64(pic){
// this.$toast.loading({
// duration: 0,
// message: '处理中...',
// forbidClick: true,
// })
// var url = "https://upload.qiniup.com/putb64/-1";
// var xhr = new XMLHttpRequest();
// xhr.onreadystatechange = () => {
// if (xhr.readyState==4){
// let getMsg = JSON.parse(xhr.responseText);
// console.log(getMsg);
// console.log(this.domain + getMsg.hash);
// console.log(this.domain + getMsg.key);
// this.image = this.domain + getMsg.key;
// this.$nextTick(()=>{
// this.$toast.clear();
// })
// }
// }
// xhr.open("POST", url, true);
// xhr.setRequestHeader("Content-Type", "application/octet-stream");
// xhr.setRequestHeader("Authorization", "UpToken " + this.token);
// xhr.send(pic);
// },
getfileReaderURL(file,callback){
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload=function(e){
callback( reader.result);
}
reader.onloadend=function(e){}
},
// 上传图片-上传图片后相应处理
sendImg(e){
if(e.target.files[0]){
if(e.target.files[0].size / 1024 / 1024 > 5){
this.$refs.referenceUpload.value = null;
this.$toast('请上传不超过5M的图片');
return;
}
this.$toast.loading({
duration: 0,
message: '上传中...',
forbidClick: true,
})
this.getfileReaderURL(e.target.files[0],(url)=>{
this.$refs.referenceUpload.value = null;
// let base64 = url.split(',');
// this.putb64(base64[1]);
this.magageImg = url;
this.magage = true;
this.$nextTick(()=>{
if (this.cropper) {
this.cropper.destroy();
}
const image = document.getElementById('image');
this.cropper = new Cropper(image, {
aspectRatio: 7 / 6,
preview: '.img-preview',
ready: (e) => {
this.$toast.clear();
console.log(e.type);
},
cropstart: (e) => {
console.log(e.type, e.detail.action);
},
cropmove: (e) => {
console.log(e.type, e.detail.action);
},
cropend: (e) => {
console.log(e.type, e.detail.action);
},
crop: (e) => {
var data = e.detail;
console.log(e.type);
},
zoom: (e) => {
console.log(e.type, e.detail.ratio);
}
});
})
});
}
},
// 编辑图片-旋转图片
rotateImg(){
this.cropper.rotate(45);
},
// 确定上传编辑好的图片
saveImg(){
let url = this.cropper.getCroppedCanvas({width:700,height:600}).toDataURL('image/jpg');
// let base64 = url.split(',');
// this.putb64(base64[1]);
this.magage = false;
// 确定上传编辑好的图片至七牛
qiniuUpFile(url,this.token).then(res=>{
console.log(res);
console.log(this.domain + res.hash);
console.log(this.domain + res.key);
this.image = this.domain + '/' + res.key;
}).catch(err=>{
console.log(err);
})
},
/*************************/
// 上传文件
sendFile(e){
if((e.target.files[0].type == '') || ((e.target.files[0].type.indexOf('image/') == -1) && (e.target.files[0].type.indexOf('/pdf') == -1))){
this.$toast('请上传图片或PDF格式文件');
return;
}
if(e.target.files[0].type.indexOf('image/') != -1){
this.filetype = 'img';
}else{
this.filetype = 'pdf';
}
if(e.target.files[0]){
if(e.target.files[0].size / 1024 / 1024 > 10){
this.$refs.referenceUploadFile.value = null;
this.$toast('请上传不超过10M的文件哦');
return;
}
this.$toast.loading({
duration: 0,
message: '上传中...',
forbidClick: true,
})
qiniuUpFile(e.target.files[0],this.token).then(res=>{
console.log(res);
console.log(this.domain + res.hash);
console.log(this.domain + res.key);
this.$refs.referenceUploadFile.value = null;
this.url = this.domain + '/' + res.key;
}).catch(err=>{
console.log(err);
})
}
},
/*************************/
// 上传视频
sendVideo(e) {
this.upvideo = '';
if (e.target.files[0]) {
if (e.target.files[0].size / 1024 / 1024 > 10) {
this.$refs.referenceUploadVideo.value = null;
this.$toast('请上传不超过' + 10 + 'M的视频哦');
return;
}
this.$toast.loading({
duration: 0,
message: '上传中...',
forbidClick: true,
})
qiniuUpFile(e.target.files[0], this.token, "video/mp4").then(res => {
// console.log(res);
// console.log(this.domain + '/' + res.hash);
// console.log(this.domain + '/' + res.key);
this.$refs.referenceUploadVideo.value = null;
this.upvideo = this.domain + '/' + res.key;
}).catch(err => {
console.log(err);
})
}
},
getVideoTime(e) {
if(e.target.duration < 3 || e.target.duration > 60){
this.$toast('本视频时间' + e.target.duration + '秒,请上传' + 3 + '秒至' + 60 + '秒以内的视频');
this.upvideo = '';
}
},
},
}
</script>
<style scoped>
.pop{ width: 100%; height: 100%; background-color: rgba(0,0,0,.5); position: fixed; left: 0; top: 0; z-index: 1;
display: flex; justify-content: center; align-items: center;
}
.pop_body{ text-align: center;}
.showimg{ width: 80vw; height: 65vh; position: relative;}
.showimg img{ width: 100%; position: relative;}
.base_btn{ display: inline-block; width: 200px; height: 70px; line-height: 70px; margin: 40px 10px 0 10px; text-align: center; color: #fff; font-size: 36px; border-radius: 45px;
background: linear-gradient(90deg, #2BC188 0%, #35CE96 100%);
box-shadow: 0px 3px 16px rgba(92, 255, 208, 0.4);
}
/* 上传文件/视频 */
.upfile_controls{ width: 200px; height: 200px; margin: 30px auto 0 auto; border-radius: 10px; border: #eee solid 2px; overflow: hidden; position: relative;}
.upfile_controls img,.upfile_controls video,.upfile_controls input{ width: 100%; height: 100%; position: absolute; left: 0; top: 0;}
.upfile_controls img{ object-fit: contain;}
.upfile_controls video{ object-fit: contain; background-color: #000;}
.upfile_controls input{ opacity: 0;}
</style>