Vue2-文件上传、下载场景功能

这篇具有很好参考价值的文章主要介绍了Vue2-文件上传、下载场景功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上传功能

在项目开发中,上传文件的应用场景非常的多,一般情况下,上传的接口都是由公司内部自己开发一套适用于任何场景都可以使用的接口,但是这意味着该接口所涉及到的工作量与技术点就非常的多,且不稳定。于是大公司选择了前者自己研发,小公司则选择了性价比更高的第三方云存储服务,国内知名的云技术服务商基本上是 阿里云 和 腾讯云。以下是腾讯云存储 COS 基本使用流程:

腾讯云存储COS

​ **对象存储(Cloud Object Storage,COS)**是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。

首先进行登录注册 > 实名认证 > 公有读私有写

  • 控制台:https://console.cloud.tencent.com/cos/bucket

    1. 创建存储桶对象,并完成相关配置项
    2. 存储桶 CORS 跨域访问控制:https://console.cloud.tencent.com/cos/bucket?bucket=hr-1305184603&region=ap-guangzhou&type=securityconfig&anchorType=corsSetting
  • 产品 API 文档:https://cloud.tencent.com/document/product/436

  • SDK 下载列表:https://console.cloud.tencent.com/cos/sdk [也可 maven 配置 / npm 下载]

  • Secret 密钥管理:https://console.cloud.tencent.com/cam/capi

使用示例

  • 安装 SDK :
npm install --save cos-js-sdk-v5
  • 使用:

index.js

import COS from 'cos-js-sdk-v5'

// 实例化 COS 对象
const cos = new COS({
    SecretID: 'AKIDWquiGXXGNIyOZU9YicGfohNnxsXw5zd1',
    SecretKey: 'A4i6F8mHbfU3MPEn69wUnqdBUXLvFJ7f'
})

// 上传配置
cos.putObject(
 {
    Bucket: 'hr-1305184603', // 存储桶名称
    Region: 'ap-guangzhou', // 存储桶所在地域
    Key: file.uid + '', // 上传的文件对象 id 唯一值,必须是字符串
    StorageClass: 'STANDARD', // 固定值
    Body: file, // 上传的文件对象
    onProgress: (progressData) => { // 上传进度事件
    	/*
    		progressData: {
    			loaded: 1005180, // 已上传文件大小
    			total: 1005180,  // 总上传文件大小
    			speed: 1100963.86,  // 总用时
    			percent: 1 // 进度 1: 完成, 0: 未开始
    		}
    	*/
    }
 },
 (err || data) => { // 上传结果回调函数
    // err 和 data :二者存其一,有 err 代表上传失败,有 data 代表上传成功,接收一个返回值
    /*
    	data: {
        	ETag: "",  // 有效期标记
            Location: "hr-1305184603.cos.ap-guangzhou.myqcloud.com/1659251801441", // 上传成功的图片地址,可添加 http:// || https:// 前缀
            headers: {content-length: '0'}, // header 头部
            statusCode: 200 // 状态码
        }
    */
  }
)

上传组件封装

uploadImg.vue

<template>
  <div class="uploadImg">
    <el-upload class="avatar-uploader" action="https://jsonplaceholder.typicode.com/posts/" :show-file-list="false" :before-upload="beforeAvatarUpload" :http-request="httpRequest" >
      <img v-if="value" v-globalImgerror="defaultImg" :src="value" class="avatar" @click.stop.prevent="isShow = true" >
      <i v-else class="el-icon-plus avatar-uploader-icon" />
    </el-upload>
    <!-- 删除按钮 -->
    <div v-if="value" class="del" @click="del">X</div>
    <!-- 预览 -->
    <el-dialog title="图片预览" width="500px" :visible.sync="isShow">
      <img style="width: 100%" :src="value" alt="">
    </el-dialog>
    <transition name="fade">
      <el-progress v-if="loading" :percentage="percentage" />
    </transition>
  </div>
</template>
<script>
import COS from 'cos-js-sdk-v5'
const cos = new COS({
  SecretId: 'AKIDNXR8bpeSF1JL8EyZopxRfdHgqGUeuEn8',
  SecretKey: 'HJ9mAbQEn7jgjY9swEI6yAamk7MN8hty'
})
export default {
  name: 'UploadImg',
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      defaultImg: require('@/assets/common/head.jpg'),
      loading: false,
      percentage: 0,
      isShow: false
      //   imageUrl: ''
    }
  },
  methods: {
    beforeAvatarUpload(file) {
      return true
    },
    httpRequest(res) {
      this.loading = true
      this.percentage = 0
      cos.putObject(
        {
          Bucket:
            'dhf481229-1305249343' /* 必须:存储桶,使用自己注册的存储桶 */,
          Region: 'ap-guangzhou' /* 存储桶所在地域,必须字段 */,
          Key: res.file.uid + '' /* 必须,要求是字符串 */,
          StorageClass: 'STANDARD', // 固定,不用修改
          Body: res.file, // 上传文件对象
          onProgress: (progressData) => {
            // 上传进度
            this.percentage = progressData.percent * 100
            if (progressData.percent === 1) {
              //   setTimeout(() => {
              this.loading = false
              //   }, 1000)
            }
            console.log(JSON.stringify(progressData))
          }
        },
        (err, data) => {
          // 上传成功的回调  err:代表错误,没有错误就代表成功  data:上传成功的接口返回值
          console.log(err || data)
          this.$emit('input', 'http://' + data.Location)
          //   this.imageUrl = 'http://' + data.Location
        }
      )
    },
    // 删除
    del() {
      this.$emit('input', '')
    }
  }
}
</script>
<style lang="scss" scoped>
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
.uploadImg {
  position: relative;
  width: 178px;
  &:hover {
    .del {
      display: block;
    }
  }
  .del {
    position: absolute;
    top: 10px;
    right: 10px;
    cursor: pointer;
    display: none;
  }
  .fade-enter-active,
  .fade-leave-active {
    transition: all 0.5s;
  }
  .fade-enter {
    opacity: 0;
    // transform: translateY(-100px);
  }
  .fade-leave-to {
    opacity: 0;
    // transform: translateY(100px);
  }
}
</style>

index.vue

<template>
  <div>
    <h3>上传v-model显示上传地址:{{ imgUrl }}</h3>
    <UploadImg v-model="imgUrl" />
    <el-upload class="avatar-uploader" action="#" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload" :http-request="httpRequest">
      <img v-if="imageUrl" :src="imageUrl" class="avatar" />
      <i v-else class="el-icon-plus avatar-uploader-icon" />
    </el-upload>
  </div>
</template>
<script>
import COS from 'cos-js-sdk-v5'
const cos = new COS({
  SecretId: 'AKIDWquiGXXGNIyOZU9YicGfohNnxsXw5zd1',
  SecretKey: 'A4i6F8mHbfU3MPEn69wUnqdBUXLvFJ7f'
})
export default {
  data() {
    return {
      imgUrl: '',
      imageUrl: ''
    }
  },
  methods: {
    // 文件上传成功回调
    handleAvatarSuccess(res, file) {
      console.log(res, file)
    },
    // 上传之前回调
    beforeAvatarUpload(file) {
      const isPng = file.type === 'image/png' || file.type === 'image/jpeg'
      const isLF2M = file.size <= 1024 * 1024 * 2
      if (!isPng) {
        this.$message.error('请上传图片文件')
        return false
      }
      if (!isLF2M) {
        this.$message.error('文件不得超过 2m')
        return false
      }
      return true
    },
    //自定义上传配置回调
    httpRequest(res) {
      // res: 封装的文件对象
      console.log(res)
      cos.putObject(
        {
          Bucket: 'hr-1305184603' /* 必须:存储桶 */,
          Region: 'ap-guangzhou' /* 存储桶所在地域,必须字段 */,
          Key: res.file.uid + '' /* 必须,要求是字符串 */,
          StorageClass: 'STANDARD', // 固定,不用修改
          Body: res.file, // 上传文件对象
          onProgress: progressData => {
            // 上传进度
            console.log(progressData)
          }
        },
        (err, data) => {
          // 上传成功的回调  err:代表错误,没有错误就代表成功  data:上传成功的接口返回值
          console.log(err || data)
          this.imageUrl = 'http://' + data.Location
        }
      )
    }
  }
}
</script>
<style>
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

下载文件相关场景

本地同源下载

链接下载

场景:同源下载文件。

解决:只需要一个 <a><iframe> 标签即可。

之所以要 <iframe> 标签是因为 <a> 标签会进行跳转,所以需要在当前页面创建一个空的、隐藏的 <iframe> 标签,让 标签的 target 指向它,让用户无感的在内部进行下载。

downloadFile(obj, name, suffix) {
   const url = window.URL.createObjectURL(new Blob([obj]))
   const iframe = document.createElement('iframe')
   iframe.name = 'iframe'
   iframe.style = 'display: none'
   document.body.appendChild(iframe)

   const link = document.createElement('a')
   link.style.display = 'none'
   link.href = url
   link.target = 'iframe' // --不刷新、跳转页面
   const fileName = parseTime(new Date()) + '-' + name + '.' + suffix
   link.setAttribute('download', fileName)

   document.body.appendChild(link)
   link.click()
   link.dispatchEvent(new MouseEvent("click"));
   window.URL.revokeObjectURL(url)

   document.body.removeChild(link)
},

文件流下载

场景:由后台来返回文件流,需要前台用 ajax 进行异步请求并处理

pdf:

const downloads = () => {
   const url = pdf.url
   const filename = pdf.title
   const x = new XMLHttpRequest()
   x.open('GET', url, true)
   x.responseType = 'blob'
   x.onload = () => {
     // 会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
     const url = window.URL.createObjectURL(x.response)
     const a = document.createElement('a')
     a.href = url
     a.download = filename
     a.click()
     a.dispatchEvent(new MouseEvent("click")); // 这里会触发两次 click,主要应对 IE
     window.URL.revokeObjectURL(url);
   }
   x.send()
}

图片:

let url = "后端返回文件流的地址"
fetch(url,{method: 'get',headers:{'Content-Type': 'image/jpeg'}}).then(
    res=>res.blob().then(blob=>{
        var reader = new FileReader();
        reader.readAsDataURL(blob);   // 转换为base64,可以直接放入a标签href
        reader.onload = function (e) {
            var down = document.createElement('a');   // 转换完成,创建一个a标签用于下载
            down.download = name;
            down.href = String(e.target.result);
            // document.appendChild(down)
            down.click();
            down.dispatchEvent(new MouseEvent("click"));
            down.remove();
        }
    })
)

跨域下载文件

场景:后台返回一个不同服务器的文件链接(不限于包括图片、pdf文件),需要前端去下载到本地。这里引发了跨域问题。

解决方案:这个由前端去解决并不是很好,最好是可以让后台先下载好将 blob 数据流返回给前端去处理。

  • 1、如果是固定的一个域名,建立一层 nginx 代理,前端访问代理服务器来绕过跨域问题
  • 2、最好的方案:由后台去下载好文件,然后返回文件流给前端去处理(跨域 => 同源)

处理代码如下:文章来源地址https://www.toymoban.com/news/detail-732283.html

图片文件处理
download(href, name) {
  let eleLink = document.createElement('a')
  eleLink.download = name
  eleLink.href = href
  eleLink.click()
  eleLink.remove()
},
downloadByBlob(url, name) {
  let image = new Image()
  image.setAttribute('crossOrigin', 'anonymous')
  image.src = url
  image.onload = () => {
    let canvas = document.createElement('canvas')
    canvas.width = image.width
    canvas.height = image.height
    let ctx = canvas.getContext('2d')
    ctx.drawImage(image, 0, 0, image.width, image.height)
    canvas.toBlob(blob => {
      let url = URL.createObjectURL(blob)
      this.download(url, name)
      // 用完释放URL对象
          URL.revokeObjectURL(url)
    })
  }
},

到了这里,关于Vue2-文件上传、下载场景功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue2+Spring Boot2.7 大文件分片上传

    之前我们文章 手把手带大家实现 vue2+Spring Boot2.7 文件上传功能 将了上传文件 但如果文件很大 就不太好处理了 按正常情况甚至因为超量而报错 这里 我弄了个足够大的文件 我们先搭建 Spring Boot2.7 环境 首先 application.yml 代码编写如下 这里 我们改了他对请求大小的限制 不然

    2024年02月11日
    浏览(48)
  • vue2文件流下载成功后文件格式错误、打不开、内容缺失

    后端采用文件流的方式将文件信息发送给前端,前端需要接收相应的流信息做出对应的操作,如接收到图片、pdf将进行预览模式,将接收到压缩包形式的则进行文件下载。后端对相应的文件进行不同的传输方式进行传输,前端则需要接收相应的信息并进行操作。 当收到图片、

    2023年04月27日
    浏览(41)
  • springboot整合vue2-uploader文件分片上传、秒传、断点续传

    vue-simple-uploader 是基于 simple-uploader.js 封装的vue上传插件。它的优点包括且不限于以下几种: 支持文件、多文件、文件夹上传;支持拖拽文件、文件夹上传 可暂停、继续上传 错误处理 支持“秒传”,通过文件判断服务端是否已存在从而实现“秒传” 分片上传 支持进度、预估

    2024年02月06日
    浏览(60)
  • vue2 pdfjs-2.8.335-dist pdf文件在线预览功能

    1、首先先将 pdfjs-2.8.335-dist 文件夹从网上搜索下载,复制到public文件夹下. 2、在components下新建组件PdfViewer.vue文件 3、在el-upload 中调用 pdf-viewer 组件 4、在el-upload 中的 on-preview方法中加上对应的src路径  internalPreview(file) { //判断需要预览的地方加 props—pdfView                

    2024年01月19日
    浏览(48)
  • 【vue2】前端实现下载后端返回的application/octet-stream文件流

    1、下载csv/txt时 此时无须修改接口的响应格式 2、下载Excel时,需要修改一下接口的响应格式为blob 另

    2024年02月11日
    浏览(55)
  • vue2中,vue.extend使用场景

    extend是Vue.js提供的一个构造器,用于创建一个组件的子类。它接受一个组件选项对象作为参数,并返回一个新的组件构造函数。 Vue.component是一个全局方法,用于注册全局组件。它接受两个参数,第一个参数是组件名称,第二个参数是组件选项对象。 extend用于在父组件内部创

    2024年02月07日
    浏览(43)
  • Vue学习计划-Vue2--VueCLi(二)vuecli脚手架创建的项目内部主要文件分析

    1. 补充: 什么叫单文件组件? 一个文件中只有一个组件 vue-cli 创建的项目中, .vue 的文件都是单文件组件,例如 App.vue 2. 进入分析 1. package.json : 项目依赖配置文件: 如图,我们说主要的属性: name : 项目的名称 version : 项目版本 scripts : 脚本入口 serve : 启动项目命令 build :

    2024年02月04日
    浏览(77)
  • vue2,使用element中的Upload 上传文件,自定义上传http-request上传,上传附件支持多选,多个文件只发送一次请求,代码里有注释

    复制直接使用,组件根据multiple是否多选来返回附件内容,支持多选就返回数据附件,则返回一个附件对象。

    2024年02月10日
    浏览(56)
  • vue2组件库-上传组件

    核心思路: 监控整个上传的流程 上传成功 上传失败 类型:拖拽 多个文件上传 跟上传强关联的属性,上传必备的字段 name: 提交的那个formData字段名 action:ajax接口路径 limit:限制提交个数 钩子函数 dom: this.$refs 选中文件 上传 按照整个上传的流程 fileList中每个对象的状态

    2024年02月08日
    浏览(48)
  • vue2上传图片image-conversion压缩

    项目中涉及上传图片,如果大体积的一般都需要压缩,这里我使用image-conversion来压缩 其实在npm中使用已经说得很明白了,我这里记录一下跟element ui上传组件配合使用 1、安装image-conversion 2、引入使用 2.1、这里配合element ui的上传组件配合使用 上传前方法中处理压缩逻辑,压

    2024年01月21日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包