vue(web) uniapp(兼容APP,小程序,H5) 阿里云oss上传

WEB上传封装

<template>
  <div class="uploadVideo">
    <div class="videoBox" v-if="!url && !isUp">
      <div class="upVideo" @click="inputChange">
        <i class="el-icon-plus"></i>
      </div>
    </div>
    <div class="videoBox">
      <el-progress v-if="isUp" type="circle" :width="200" :percentage="videoUploadPercent"></el-progress>
    </div>
    <video id="vide" v-if="url" :src="url" class="videoAvatar" controls="controls"></video>
    <div class="optionBtn">
      <el-button type="primary" size="small" @click="inputChange" v-if="url">重新上传</el-button>
      <el-button type="danger" size="small" @click="cancelUp" v-if="isUp">取消上传</el-button>
    </div>
    <p class="Upload_pictures">
      <span>最多可以上传1个视频,建议大小50M,推荐格式mp4,点击视频重新上传</span>
    </p>
    <input class="inputer" ref="inputer" type="file" accept="video/*" @change="httpRequest" />
  </div>
</template>

<script>
import OSS from 'ali-oss'
import {
  v4 as uuidv4
} from "uuid"
import api from '@/api'
export default {
  props: {
    VideoPath: {
      type: String,
      default() {
        return ''
      }
    }
  },
  data() {
    return {
      uploadImgUrl: process.env.VUE_APP_API + "upload-video", // 上传的视频服务器地址
      videoFlag: false,
      videoUploadPercent: 0,
      cancel: false,
      isUp: false,
      url: '',
      client: null
    };
  },
  created() {

  },
  watch: {
    VideoPath(val) {
      this.url = val
    },
  },
  methods: {
    async httpRequest() {
      this.isUp = true
      this.videoUploadPercent = 0
      this.url = ''
      this.$emit('Change', '')
      let that = this
      let file = this.$refs.inputer.files[0]
      var fileSize = file.size / 1024 / 1024 < 1000;
      if (['video/mp4', 'video/ogg', 'video/flv', 'video/avi', 'video/wmv', 'video/rmvb', 'video/mov'].indexOf(file.type) == -1) {
        this.$notify.warning({
          title: "警告",
          message: "请上传正确的视频格式",
        });
        return false;
      }
      if (!fileSize) {
        this.$notify.warning({
          title: "警告",
          message: "视频大小不能超过1000MB",
        });
        return false;
      }
      const { data } = await api.uploadParams()
      if (!data.accessKeyID) {
        return
      }
      this.client = new OSS({
        region: data.region,
        bucket: data.bucket,
        stsToken: data.stsToken,
        accessKeyId: data.accessKeyID, //AccessKey
        accessKeySecret: data.accessKeySecret, //秘钥
      });
      const suffix = file.name.substr(file.name.indexOf('.'))

      let url = '/video/' + uuidv4() + suffix
      const options = {
        // 获取分片上传进度、断点和返回值。
        progress: (p, cpt, res) => {
          this.videoUploadPercent = Math.floor(p * 100)
          console.log(cpt)
          if (this.cancel) {
            this.client.abortMultipartUpload(cpt.name, cpt.uploadId)
            this.cancel = false
          }
        },
        // 设置并发上传的分片数量。
        parallel: 4,
        // 设置分片大小。默认值为1 MB,最小值为100 KB。
        partSize: 1024 * 1024,
        // headers,
        // 自定义元数据,通过HeadObject接口可以获取Object的元数据。
        // meta: { year: 2020, people: "test" },
        mime: "text/plain",
      };
      try {
        const {
          res,
          name
        } = await this.client.multipartUpload(url, file, options)
        if (res.status == 200) {
          let videoUrl = 'https://y-video.ibookgames.com' + name
          that.onSuccess(videoUrl)
        }
      } catch (e) {
        that.onError('上传失败');
      }
    },
    inputChange() {
      this.$refs.inputer.click()
    },
    onError(e) {
      this.url = ''
      this.isUp = false
      this.$emit('Change', '')
    },
    onSuccess(e) {
      this.url = e
      this.isUp = false
      this.$emit('Change', e)
    },
    cancelUp(e) {
      this.$refs.inputer.value = ''
      this.cancel = true
    },

  }
};
</script>

<style  scoped>
.uploadVideo {
  display: flex;
  flex-direction: column;
}

.videoAvatar {
  width: 200px;
}

.optionBtn {
  width: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 20px;
}

.upVideo {
  width: 200px;
  height: 100px;
  border: 1px dashed#999999;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  position: relative;
}


.el-icon-plus {
  font-size: 40px;
  color: #999999;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.inputer {
  width: 0;
  height: 0;
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
}
</style>

调用

<uploadImage :limit="6" ref="adtiveUp" @getUrl="ShowUrl($event, '自己需要携带的参数')"
            @delUrl="ShowUrl($event, '自己需要携带的参数')" />

UNIAPP上传封装

import utils from '@/utils/utils.js';
import store from '@/store'
import crypto from 'crypto-js';
import api from '@/request/index'
import {
	v4 as uuidv4
} from 'uuid';
import {
	Base64
} from 'js-base64'
// #ifdef APP-VUE
import permision from "@/common/permission.js"
// #endif
class Upload {
	constructor(arg) {
		this.uploadUrl = ''; // 上传文件地址
		this.uploadList = []; // 上传文件列表
		this.uploadCurrentIndex = 0; // 上传到第几个文件
		this.uploadParams = {}; //上传参数
		this.uploadLoading = true; //上传动画默认为true
		this.sourceType = []; //album 从相册选图,camera 使用相机,默认二者都有。如需直接开相机或直接选相册,请只使用一个选项
		this.sizeType = []; //original 原图,compressed 压缩图,默认二者都有
	}
	// 选择图片
	choiceImg() {

		const that = this;
		uni.chooseImage({
			count: that.uploadParams.MaxNumber,
			sourceType: this.sourceType,
			sizeType: this.sizeType,
			async success(res) {
				const tempFilePaths = res.tempFilePaths;
				that.uploadList = res.tempFiles;
				if (that.uploadParams.MaxNumber && (that.uploadParams.MaxNumber < tempFilePaths.length)) {
					utils.TextToast('超出文件上传最大数量' + that.uploadParams.MaxNumber);
					that.ressetUpload();
				} else {
					that.uploadData();
				}
			},
			fail(err) {
				if (err.errMsg.indexOf('cancel') === -1) {
					utils.TextToast('选择相册失败');
					console.error(err);
				}
			},
			complete() {
				that.hideLoading();
			}
		});
	}
	upLoading(msg) {
		utils.showLoading(msg || '上传中...', true)
	}
	hideLoading() {
		utils.hideLoading();
	}
	// 上传文件
	async uploadData() {
		const that = this;
		that.uploadLoading && that.upLoading();
		let data = that.uploadParams.params
		let fileData = that.uploadList[that.uploadCurrentIndex]
		// 图片大小
		const imgSize = fileData.size
		if (imgSize > 10485760) {
			utils.TextToast("图片超出大小限制,图片不得大于10M")
			return false;
		}
		let newName = fileData.name || fileData.path
		let name = uuidv4() + newName.substr(newName.lastIndexOf('.'))
		let pramsData = await that.getFormDataParams()
		uni.getImageInfo({
			src: fileData.path,
			complete(image) {
				uni.uploadFile({
					url: that.uploadUrl,
					filePath: fileData.path,
					formData: {
						...pramsData,
						key: name,
						'success_action_status': '200',
					},
					fileType: 'image',
					name: 'file',
					success: (res) => {
						const {
							successBack,
							failBack,
							complateBack,
							callback
						} = that.uploadParams;
						if (res.statusCode === 200) {
							let url = that.uploadUrl + '/' + name
							successBack(url);
							// 根据 that.uploadCurrentIndex 判断是否需要继续上传图片
							if (that.uploadCurrentIndex < that.uploadList.length - 1) {
								that.uploadCurrentIndex += 1;
								that.uploadData();
							} else {
								that.ressetUpload();
								callback && callback();
							}
						} else {
							that.ressetUpload();
							failBack(data);
						}
						complateBack && complateBack(res);
					},
					fail(err) {
						that.ressetUpload();
						utils.TextToast('上传图片失败');
						console.log(err);
					}
				});
			}
		});
	}
	computeSignature(accessKeySecret, canonicalString) {
		return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
	}
	async getFormDataParams() {
		const date = new Date();
		date.setHours(date.getHours() + 1);
		const policyText = {
			expiration: date.toISOString(), // 设置policy过期时间。
			conditions: [
				// 限制上传大小。
				["content-length-range", 0, 1024 * 1024 * 1024],
			],
		};
		const credentials = await api('init.uploadParams')
		this.uploadUrl = credentials.data.endpoint
		const policy = Base64.encode(JSON.stringify(policyText)) // policy必须为base64的string。
		const signature = this.computeSignature(credentials.data.accessKeySecret, policy)
		const formData = {
			OSSAccessKeyId: credentials.data.accessKeyID,
			signature,
			policy,
			'x-oss-security-token': credentials.data.stsToken
		}
		return formData
	}
	// 上传完成后重置数据
	ressetUpload() {
		this.uploadCurrentIndex = 0;
		this.uploadList = [];
		this.uploadLoading && this.hideLoading();
	}
	async uploadMetod(paramsData) {
		if (typeof paramsData !== 'object') {
			throw Error('upload params is must a object');
		}
		this.uploadParams = paramsData;
		this.uploadLoading = paramsData.uploadLoading !== undefined ? paramsData.uploadLoading : true;
		this.sourceType = paramsData.sourceType !== undefined ? paramsData.sourceType : ['album', 'camera'];
		this.sizeType = paramsData.sizeType !== undefined ? paramsData.sizeType : ['original', 'compressed'];
		this.choiceImg();
	}
}
export default new Upload()

调用

// 上传图片
			async UploadImgs() {
				let that = this
				ossUp.uploadMetod({
					MaxNumber: 1,
					successBack(res) {
						that.userInfo.bg_pic = res
						that.setBg()
					},
					callback(res) {},
					failBack(err) {
						that.$utils.TextToast(err.message);
					},
				});
			},

你可能感兴趣的:(前端,vue.js,uni-app,阿里云)