1、安装ali-oss

npm install ali-oss --save

2、oss方法封装

新建utils/ali-oss-upload.js文件(代码如下)

const OSS = require('ali-oss')// 文档链接:https://help.aliyun.com/document_detail/32068.html?spm=a2c4g.11186623.6.1291.86b3c107IHjkTR
/*** 阿里 OSS 服务 OSS 对象* [accessKeyId] {String}:通过阿里云控制台创建的AccessKey。* [accessKeySecret] {String}:通过阿里云控制台创建的AccessSecret。* [stsToken] {String}:使用临时授权方式,详情请参见使用 STS 进行临时授权。* [bucket] {String}:通过控制台或PutBucket创建的bucket。* [endpoint] {String}:OSS域名。* [region] {String}:bucket所在的区域, 默认oss-cn-hangzhou。* [internal] {Boolean}:是否使用阿里云内网访问,默认false。比如通过ECS访问OSS,则设置为true,采用internal的endpoint可节约费用。* [cname] {Boolean}:是否支持上传自定义域名,默认false。如果cname为true,endpoint传入自定义域名时,自定义域名需要先同bucket进行绑定。* [isRequestPay] {Boolean}:bucket是否开启请求者付费模式,默认false。具体可查看请求者付费模式。* [secure] {Boolean}:(secure: true)则使用HTTPS,(secure: false)则使用HTTP,详情请查看常见问题。* [timeout] {String|Number}:超时时间,默认60s。*/
const client = new OSS({region: '',accessKeyId: '',accessKeySecret: '',bucket: ''
})/*** OSS 服务文件上传单个文件* 同步方式:基于 async 和 await 方式,异步编程同步化。* @param {String} objectName 可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。* @param {file} file 本地文件或者文件路径*/
export async function ossPut(objectName, file) {try {const result = await client.put(objectName, file)// console.log(result)return result} catch (error) {// console.log(error)return error}
}/*** OSS 服务文件上传单个文件* 异步方式:API 接口返回 Promise* @param {String} objectName 可以自定义为文件名(例如file.txt)或目录(例如abc/test/file.txt)的形式,实现将文件上传至当前Bucket或Bucket下的指定目录。* @param {file} file 本地文件或者文件路径*/
export async function ossAsyncPut(objectName, file) {return new Promise((resolve, reject) => {client.put(objectName, file).then(res => {resolve(res)}).catch(error => {resolve(error)})})
}/*** OSS 服务文件下载单个文件* 同步方式:基于 async 和 await 方式,异步编程同步化。* @param {String} objectName*/
export async function ossGet(objectName) {try {const result = await client.get(objectName)// console.log(result)return result} catch (error) {// console.log(error)return error}
}/*** OSS 服务文件下载单个文件* 异步方式:API 接口返回 Promise* @param {String} objectName*/
export async function ossAsyncGet(objectName) {return new Promise((resolve, reject) => {client.get(objectName).then(res => {resolve(res)}).catch(error => {reject(error)})})
}/*** OSS 服务文件删除单个文件* @param {String} objectName*/
export async function ossDelete(objectName) {try {const result = await client.delete(objectName)return result} catch (error) {// console.log(error)return error}
}

3、组件封装

  1. 图片上传
    1) 涉及到图片转换的方法如下(utils/index.js)
/*** base64ToFileObject base64 码转 blob 二进制,再转 file 对象* @param  {[type]} base64 [base64码]* @param  {string} fileName [转码后 file 对象的名称]* @return {[type]} newFile[返回新的file对象]*/
export function base64ToFileObject(base64, fileName = 'file') {const mime = base64.split(',')[0].match(/:(.*?);/)[1]base64 = base64.split(',')[1]base64 = window.atob(base64)const u8arr = new Uint8Array(base64.length)for (let i = 0; i < base64.length; i++) {u8arr[i] = base64.charCodeAt(i)}const blob = new Blob([u8arr], { type: mime })const suffix = mime.split('/')[1]return new File([blob], `${fileName}.${suffix}`, { type: mime })
}/*** imgToBase64 压缩图片* @param  {[type]} file      [file对象 event.target.files[0]]* @param  {[type]} maxWidth  [最大宽度]* @param  {[type]} maxHeight [最大高度]* @return {[type]}           [description]*/export function imgToBase64(file, maxWidth, maxHeight) {return new Promise((resolve, reject) => {// 压缩图片需要的一些元素和对象const reader = new FileReader()const img = new Image()img.onload = function() {// 图片原始尺寸const originWidth = this.widthconst originHeight = this.height// 目标尺寸let targetWidth = originWidthlet targetHeight = originHeight// 图片尺寸超过400x400的限制if (originWidth > maxWidth || originHeight > maxHeight) {if (originWidth / originHeight > maxWidth / maxHeight) {// 更宽,按照宽度限定尺寸targetWidth = maxWidthtargetHeight = Math.round(maxWidth * (originHeight / originWidth))} else {targetHeight = maxHeighttargetWidth = Math.round(maxHeight * (originWidth / originHeight))}}// 缩放图片需要的canvasconst canvas = document.createElement('canvas')const context = canvas.getContext('2d')// canvas对图片进行缩放canvas.width = targetWidthcanvas.height = targetHeight// 清除画布context.clearRect(0, 0, targetWidth, targetHeight)// 图片压缩context.drawImage(img, 0, 0, targetWidth, targetHeight)const base64 = canvas.toDataURL('image/jpeg', 0.8) // 压缩后质量// const base64 = canvas.toDataURL()// console.log(canvas.toDataURL());resolve(base64)}reader.onload = function(e) {img.src = e.target.result}reader.readAsDataURL(file)})
}

2)组件封装,新建uploadImg/index.vue文件,代码如下

<!--* @Description:图片上传* @Author: duyan* @Date: 2021-10-27 19:44:02* @LastEditTime: 2021-11-19 16:05:57* @LastEditors: duyan
-->
<template><div class="uploadImg"><el-upload:class="(maxCount>imgLength)?'uploadImgContent':'uploadImgContentNone'":file-list="value":limit="maxCount":drag="isDrag":http-request="onUploadFile":before-upload="handleBeforeUpload":on-preview="handlePictureCardPreview":on-remove="handleRemove":on-error="handleError"v-bind="$attrs"action=""accept="image/png,image/jpg,image/jpeg"list-type="picture-card"v-on="$listeners"><i slot="default" class="el-icon-plus"/><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过2M</div></el-upload><el-dialog :visible.sync="dialogVisible" width="100%" append-to-body><img :src="dialogImageUrl" height="100%" alt=""></el-dialog></div>
</template><script>
import { imgToBase64, base64ToFileObject } from '@/utils'
import { ossAsyncPut, ossDelete } from '@/utils/ali-oss-upload.js'
import { v4 as uuidv4 } from 'uuid'
export default {// 名字name: 'UploadImg',// 部件components: {},model: {prop: 'fileList'},// 静态props: {fileList: {type: Array,default: () => []},// 是否直接上传到 OSS 服务isPutOss: {type: Boolean,default: false},// 图片上传到 OSS 服务上的存储目录ossPathPrefix: {type: String,default: ''},// 图片上传数maxCount: {type: Number,default: 1},isDrag: {type: Boolean,default: false},// eslint-disable-next-line vue/require-default-propuploadSuccess: Function,// eslint-disable-next-line vue/require-default-propafterRead: Function},// 数据data() {return {dialogImageUrl: '',dialogVisible: false,imgLength: 0}},// 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;computed: {value: {get(val) {// eslint-disable-next-line vue/no-side-effects-in-computed-propertiesthis.imgLength = this.fileList.lengthreturn this.fileList},set(val) {this.imgLength = val.lengththis.$emit('input', val)}}},// 对象内部的属性监听,也叫深度监听watch: {},// 请求数据created() {},mounted() {},// 方法表示一个具体的操作,主要书写业务逻辑;methods: {// 图片上传onUploadFile(file) {// 上传完成this.afterRead && this.afterRead(file)// 上传ossthis.isPutOss && this.onUpload(file)},onUpload(file) {file.status = 'uploading'file.message = '上传中...'this.uploaded(file.file).then(response => {const { url } = responsefile.url = urlfile.status = 'done'file.message = '上传成功'this.value.push(file)this.$emit('input', this.value)// this.uploadSuccess(file)this.$forceUpdate()// 强制渲染}).catch(() => {file.status = 'failed'file.message = '上传失败'file.url = nullthis.$forceUpdate()})},/*** 文件上传至阿里 OSS 服务*/uploaded(file) {return new Promise((resolve, reject) => {const suffix = file.type.split('/')[1]const fileName = `${this.ossPathPrefix}/${uuidv4()}.${suffix}`ossAsyncPut(fileName, file).then(({ res, url }) => {// console.log(res)// console.log(url)if (res && res.status === 200) {// console.log('上传成功')resolve({ res, url })} else {// console.log('上传失败')reject(new Error('图片上传 OSS 服务失败!'))}})})},// 图片从oss上删除_delete(file) {console.log(file)if (file.url) {const startIndex = file.url.indexOf(this.ossPathPrefix)const objectName = file.url.substr(startIndex)ossDelete(objectName).then(res => {})}},handleBeforeUpload(file) {return new Promise((resolve, reject) => {const fileType = ['image/png', 'image/jpg', 'image/jpeg']if (!fileType.includes(file.type)) {this.$notify.warning({title: '警告',message: '请上传格式为image/png, image/jpg, image/jpeg的图片'})reject()}// 图片压缩后校验图片大小imgToBase64(file, 800, 800).then(base64 => {const resultFile = base64ToFileObject(base64)const isNeed = resultFile.size / 1024 < 200// console.log(resultFile)// console.log(resultFile.type, isNeed)if (!isNeed) {this.$notify.warning({title: '警告',message: '图片过大'})reject()}resolve()})})},handlePictureCardPreview(file) {this.dialogImageUrl = file.urlthis.dialogVisible = true},handleRemove(file, fileList) {this.value = fileListthis._delete(file)this.$forceUpdate()},handleError(err, file, fileList) {console.log('error:', err, file, fileList)}}
}
</script><style scoped lang="scss">
.uploadImg{.uploadImgContent{::v-deep .el-upload{display: inline-block !important ;}}.uploadImgContentNone{::v-deep .el-upload{display: none !important;}}
}::v-deep .el-dialog{margin: 5vh 0 !important;background: none;.el-dialog__headerbtn .el-dialog__close {color: #dddddd;border: 3px solid #dddddd;border-radius: 50%;font-size: 28px;}.el-dialog__body{height: calc( 100vh - 20vh );overflow: hidden;padding:0px 10px 10px 10px;text-align: center;}}
</style>
  1. 文件上传封装
    1) 文件类型使用及判断见此处
    2) 新建uploadFile/index.vue文件,代码如下
<!--* @Description:文件上传* @Author: duyan* @Date: 2021-10-27 19:44:02* @LastEditTime: 2021-12-21 11:29:30* @LastEditors: duyan
-->
<template><div class="uploadImg"><el-upload:class="(maxCount>imgLength)?'uploadImgContent':'uploadImgContentNone'":file-list="value":limit="maxCount":drag="isDrag":http-request="onUploadFile":before-upload="handleBeforeUpload":on-preview="handlePictureCardPreview":on-remove="handleRemove":on-error="handleError"v-bind="$attrs":accept="fileType":show-file-list="isShowFileList"action=""v-on="$listeners"><div v-show="value.length<maxCount"><!-- 模板下载 --><div v-if="templateDownload"><el-dropdown split-button type="success"><i class="el-icon-upload2"/>{{ btnLabel }}<el-dropdown-menu slot="dropdown"><el-dropdown-item icon="el-icon-download"><!-- <div style="display: inline-block; height:32px;width:100px;background-color:#11b95c;border:transparent;text-align:center;line-height:32px;border-radius:3px;"> --><a :href="downloadUrl">下载导入模板</a><!-- </div> --></el-dropdown-item></el-dropdown-menu></el-dropdown></div><div v-else><el-button size="small" icon="el-icon-plus" type="primary">{{ btnLabel }}</el-button><div slot="tip" class="el-upload__tip">只能上传{{ fileType }}文件</div></div></div></el-upload></div>
</template><script>
import { ossAsyncPut, ossDelete } from '@/utils/ali-oss-upload.js'
import { v4 as uuidv4 } from 'uuid'
export default {// 名字name: 'UploadImg',// 部件components: {},model: {prop: 'fileList'},// 静态props: {// 文件listfileList: {type: Array,default: () => []},// 是否直接上传到 OSS 服务isPutOss: {type: Boolean,default: false},// 文件上传到 OSS 服务上的存储目录ossPathPrefix: {type: String,default: ''},// 文件上传数maxCount: {type: Number,default: 1},isDrag: {type: Boolean,default: false},// 文件类型fileType: {type: String,default: () => '.pdf'},fileTypeList: {type: Array,default: () => {return ['application/pdf', 'application/doc', 'application/docx']}},// 按钮文字btnLabel: {type: String,default: '点击上传'},// 是否显示已上传文件列表isShowFileList: {type: Boolean,default: true},// 是否进行模板下载templateDownload: {type: Boolean,default: false},// 模板下载链接downloadUrl: {type: String,default: 'https://yzwy1-app.oss-cn-shenzhen.aliyuncs.com/communityModel.xlsx'},// eslint-disable-next-line vue/require-default-propuploadSuccess: Function,// eslint-disable-next-line vue/require-default-propafterRead: Function},// 数据data() {return {dialogImageUrl: '',dialogVisible: false,imgLength: 0}},// 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;computed: {value: {get(val) {// eslint-disable-next-line vue/no-side-effects-in-computed-propertiesthis.imgLength = this.fileList.lengthreturn this.fileList},set(val) {this.imgLength = val.lengththis.$emit('input', val)}}},// 对象内部的属性监听,也叫深度监听watch: {},// 请求数据created() {},mounted() {},// 方法表示一个具体的操作,主要书写业务逻辑;methods: {// 文件上传onUploadFile(file) {// 上传完成this.afterRead && this.afterRead(file)// 上传ossthis.isPutOss && this.onUpload(file)},onUpload(file) {file.status = 'uploading'file.message = '上传中...'this.uploaded(file.file).then(response => {const { url } = responsefile.url = urlfile.status = 'done'file.message = '上传成功'file.name = file.file.namethis.value.push(file)this.$emit('input', this.value)// this.uploadSuccess(file)this.$forceUpdate()// 强制渲染}).catch(() => {file.status = 'failed'file.message = '上传失败'file.url = nullthis.$forceUpdate()})},/*** 文件上传至阿里 OSS 服务*/uploaded(file) {return new Promise((resolve, reject) => {const suffix = file.type.split('/')[1]const fileName = `${this.ossPathPrefix}/${uuidv4()}.${suffix}`ossAsyncPut(fileName, file).then(({ res, url }) => {// console.log(res)// console.log(url)if (res && res.status === 200) {// console.log('上传成功')resolve({ res, url })} else {// console.log('上传失败')reject(new Error('文件上传 OSS 服务失败!'))}})})},// 文件从oss上删除_delete(file) {console.log(file)if (file.url) {const startIndex = file.url.indexOf(this.ossPathPrefix)const objectName = file.url.substr(startIndex)ossDelete(objectName).then(res => {})}},handleBeforeUpload(file) {return new Promise((resolve, reject) => {const fileType = this.fileTypeList// console.log('fileType----', fileType)// console.log('file----', file)if (!fileType.includes(file.type)) {this.$notify.warning({title: '警告',message: '请上传格式为' + this.fileType + '的文件'})reject()}resolve()})},handlePictureCardPreview(file) {this.dialogImageUrl = file.urlthis.dialogVisible = true},handleRemove(file, fileList) {this.value = fileListthis._delete(file)this.$forceUpdate()},handleError(err, file, fileList) {console.log('error:', err, file, fileList)}}
}
</script><style scoped lang="scss">
.uploadImg{.uploadImgContent{::v-deep .el-upload{display: inline-block !important ;}}.uploadImgContentNone{::v-deep .el-upload{display: none !important;}}
}::v-deep .el-dialog{margin: 5vh 0 !important;background: none;.el-dialog__headerbtn .el-dialog__close {color: #dddddd;border: 3px solid #dddddd;border-radius: 50%;font-size: 28px;}.el-dialog__body{height: calc( 100vh - 20vh );overflow: hidden;padding:0px 10px 10px 10px;text-align: center;}}.el-dropdown {vertical-align: top;}.el-dropdown + .el-dropdown {margin-left: 15px;}.el-icon-arrow-down {font-size: 12px;}
</style>

4.引入使用

代码如下:

<!--* @Description:组件使用* @Author: duyan* @Date: 2021-12-20 10:37:07* @LastEditTime: 2021-12-31 15:30:11* @LastEditors: duyan
-->
<template><div class="community-administrative"><!-- 上传本地返回 --><div style="line-height:35px;">上传表格文件本地返回:</div><upload-file:file-type="'.xls,.xlsx'":file-type-list="['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','application/vnd.ms-excel']"v-model="fileListFile":is-put-oss="false":btn-label="downloadLabel":max-count="1":template-download="true":is-show-file-list="false":download-url="'模板下载链接'":after-read="afterRead"/><!-- 上传至oss返回 --><div style="line-height:35px;">上传pdf文件至oss:</div><upload-file:file-type="'.pdf'":file-type-list="['application/pdf']"v-model="fileListPdf":is-put-oss="true":max-count="1"@input="uploadSuccess"/><div style="line-height:35px;">上传图片文件至oss:</div><upload-img v-model="fileList" :is-put-oss="true" :max-count="1" :oss-path-prefix="'yzsurvey_file/PC'" @input="uploadSuccess"/></div>
</template><script>
import uploadFile from '@/views/components/uploadFile/index'
import uploadImg from '@/views/components/uploadImg/index'export default {// 名字name: 'UploadFile',// 部件components: {uploadFile,uploadImg},// 静态props: {},// 数据data() {return {// word文件fileListFile: [],// word文件文本downloadLabel: '导入至本地文件及模板下载',// Pdf文件fileListPdf: [],// 图片文件文件fileList: []}},// 属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;computed: {},// 对象内部的属性监听,也叫深度监听watch: {},// 请求数据created() {},mounted() {},// 方法表示一个具体的操作,主要书写业务逻辑;methods: {/*** @description:文件上传成功返回* @param  {*}* @return {*}* @param {*} file 本地文件信息*/afterRead(file) {console.log('file-----', file)},/*** @description:图片/文件上传线上成功返回* @param  {*}* @return {*}* @param {*} data 文件信息及线上链接*/uploadSuccess(data) {console.log('imageData-----', data)}}
}
</script><style scoped lang="scss">
.community-administrative{padding:10px 10px 0 10px;
}
</style>

效果展示如下:

文见传入格式点此处查看

使用以上组件
存在问题:上传会存在上下闪动问题
出现原因:fileList双向绑定会导致value赋值两次
点此处进行办法解决>>

vue+el-upload组件封装(图片,文件上传至oss阿里云)相关推荐

  1. 如何将本地文件上传到code阿里云

    一.首先要有自己的阿里云账号和已下载GIt软件 二.登录到阿里云项目 三.添加项目,输入项目名称,最好使用英文,点击确定,这个时候你的项目里面是没有文件的,但是下面有上传文件的提示 四.把本地文件上传 ...

  2. upload组件多个文件上传、自定义文件列表显示及手动上传

    1.多个上传和上传单个 1)由 multiple属性 来控制 2)保存state时,注意存的List内容即可 //参数 uploadProps={name:'file', //接口入参名accept: ...

  3. 使用饿了么update组件 实现多文件上传到后台以及本地图片显示功能

    使用饿了么update组件 实现多文件上传到后台以及本地图片显示功能 查了很多博客,终于弄出来了.我就大概说一下.我的业务内容是要把一个表单统一上传上去,而且其中有字段也有图片. <div cl ...

  4. ant design vue 中Upload组件如何自定义文件列表的样式

    ant design vue 中Upload组件如何自定义文件列表的样式 问题 历程 UploadList 组件源码 h() 方法 实现 注 问题 技术:vue.ant design vue 在开发项 ...

  5. vue图片/文件上传

    vue上传图片/文件的方式: vue上传图片有两种:服务器直传和图片接口上传 注意:上传文件(图片除外)必须是config.headers = { 'Content-Type': 'multipart ...

  6. axios文件上传 formdata_基于业务场景下的图片/文件上传方案总结

    图片/文件上传组是企业项目开发中必不可少的环节之一, 但凡涉及到用户模块的都会有图片/文件上传需求, 在很多第三方组件库(ant desigin, element ui)中它也是基础组件之一. 接下来 ...

  7. Vue + Element+ ASP.NET Core WebAPI 文件上传下载

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备asp.net后端文件上传的API Uplo ...

  8. php中图片文件上传,显示缩略图

    php中图片文件上传,显示缩略图 htm代码块: <meta charset="utf-8" /> <style>img {max-width: 100px ...

  9. Vue实战篇五:实现文件上传

    系列文章目录 Vue基础篇一:编写第一个Vue程序 Vue基础篇二:Vue组件的核心概念 Vue基础篇三:Vue的计算属性与侦听器 Vue基础篇四:Vue的生命周期(秒杀案例实战) Vue基础篇五:V ...

最新文章

  1. Fragment的setUserVisibleHint方法实现懒加载
  2. Angular2 富文本编辑器 ng2-ckeditor 的使用
  3. MATLAB中的ind2vec和vec2ind函数
  4. numpy.core.umath failed to import 如何解决
  5. LeetCode:85. 最大矩形
  6. Python这么热,要不要追赶Python学习热潮?
  7. CSDN下载频道2014年11月4日本-5日常维护公告
  8. OSPF第十章:OSPF 一
  9. Android One和Android Go有什么区别?
  10. 多面体 (Multipatch)
  11. python datetime和字符串如何相互转化?
  12. Tensorflow——Dropout(解决过拟合问题)
  13. win10 java8安装包双击之后完全没反应
  14. 该如何彻底删除电脑上的软件卸载残留文件?
  15. 【自学Flutter】3.2 图片的填充样式
  16. 数智时代,英特尔的“三个火枪手”
  17. Qt学习之使用QLabel实现超链接(点击QLabel直接跳转到网页链接)
  18. LWC 66: 759. Employee Free Time
  19. Dynamics 365 多租户?多实例?
  20. python歌词分析_Python 词云分析周杰伦新歌《说好不哭》

热门文章

  1. grafana 画拓扑图 能不能_干货|告诉你标准漂亮的网络拓扑图是怎么画出来的?...
  2. 宝付正式成为杭州跨境电子商务协会理事单位
  3. Rational Rose安装
  4. 我是怎么跟面试官聊Map集合的
  5. VIJOS-P1404-遭遇战
  6. Al-NaBiO3水解产氢复合材料,镁-铝基氢化物复合水解产氢材料
  7. 多点温度采集系统设计c语言,单片机多点(八路)DS18B20温度采集系统仿真与源码...
  8. mysql pid文件作用_pid文件的作用
  9. 德邦快递怎么根据单号批量查询物流信息
  10. 应聘计算机程序员英文,应聘计算机程序员的英文简历