JS 文件上传 下载文件 批量下载

本文介绍了前端技术中文件上传和下载的基本原理与实现方法。涵盖了使用input标签选择文件、html2canvas生成图片并上传,以及不同场景下文件的下载技术。

理解

无论是上传还是下载,对前端来说,都是对数据流进行操作。
常见情况包括:

  • 1、前端使用 input type=‘file’ 标签进行文件读取 获取到file对象这种类型的数据流,将其传给接口
  • 2、前端使用html2canvas等插件进行截图,拿到的是生成后保存在内存中base64编码的二进制数据流, 此时需要根据接口的要求转成对应格式的数据在上传保存。
  • 3.后台返回文件地址 前端访问地址进行文件下载
  • 大部分情况下文件上传后台要求的都是formData对象的格式

文件上传案例


    data(){
        return {
            filename:'',
            inputFilee:'',

            uploaded:false,
        }
    },
    methods: {
        // 选择文件
        chooseFile(){
           this.inputFilee = document.createElement('input');
           this.inputFilee.type = 'file';
           this.inputFilee.addEventListener('change', this.chang);
           // 只允许excel文件
           this.inputFilee.accept = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel';
           this.inputFilee.click();
        },
        chang(){
            this.filename = this.inputFilee.files[0].name;
        },
        // 点击上传  待补全
        upload(){  
            if(this.inputFilee===''){
                this.$message.error('请选择文件')
                return
            }
            // formData.append("uploadFile",this.inputFilee.files[0])
            // http.getFileUrl(`/ufile/upload/img`,formData).then(res => {
            //     if(res.errCode==='00'){
            //         this.uploaded = true;
            //         this.filename = '';
            //         this.inputFilee = '';
            //     }  
            // })
            this.uploaded = true;
            this.filename = '';
            this.inputFilee = '';
        },
        // 重新上传
        reUpload(){
            this.uploaded = false;
        },
    },

html2canv生成图片上传案例

		//文件上传完成后  上传后台文件服务器返回的文件地址链接
        submit(){
         this.write_title_img_url = await this.base64ImgtoFile(await this.createImg('printContent'));               
        },
    methods: {
        async createImg(whichOne){
            return new Promise(resolve=>{
                let view = document.getElementById(whichOne);
                let iframe = view.children[0].children[0].getElementsByClassName('edui-editor-iframeholder edui-default')[0].children[0].contentWindow.document;
                // await this.$nextTick();// this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
                resolve(this.makeImg(iframe.getElementsByClassName('view')[0].children[1].children[0]))  
            })
        },
        //插件截图
       makeImg(printContent){
            return new Promise(resolve=>{
                html2canvas(printContent, {
                    scale: 2,
                    dpi: 2000,
                    height: printContent.clientHeight + 5, // dom 原始宽度
                    width: printContent.clientWidth + 5, // dom 原始宽度
                    scrollY: 0, // 偏移值
                    scrollX: 0,
                    useCORS: true// 跨域
                }).then(canvas => {
                    let dataURL = canvas.toDataURL('image/png');
                    resolve(dataURL);
                }).catch(err => {
                    console.log(err);
                });
            })
        },
        // 工具函数 base64转换
        async base64ImgtoFile(data) {
            return new Promise(resolve=>{
                var form=document.forms[0];  
                var formData = new FormData(form);
                let filename = this.revtimeToString(new Date)+'.png'
                var arr = data.split(','), mime = arr[0].match(/:(.*?);/)[1],
                    bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
                while(n--){
                    u8arr[n] = bstr.charCodeAt(n);
                }
                let file = new File([u8arr], filename, {type:mime});

                formData.append("uploadFile",file)
                http.getFileUrl(`........后台地址`,formData).then(res => {
                    resolve(res.data)       
                })
            })
        },
        
    },

提出下载报表数据的需求,且有格式要求.
数据处理原理与之前一样,根据需求修改逻辑即可.以下是关于JS文件下载的学习:(直接下载页面数据,无需调用后台)

 var result = ["张三","李四","王五"];//处理好的要下载的数据集result
 var blob = new Blob(["\ufeff" + result.join("")], {type: 'text/csv'}); //  ufeff解决乱码问题
 var downloadLink = document.createElement("a");
 downloadLink.setAttribute("href", URL.createObjectURL(blob));// 字符内容转变成blob地址
  //下面设置文件名  点击触发后移除
 var fileName="测试";
 fileName=fileName.replace(new RegExp(">>", "g"),".");
 fileName+="."+CurentTime()+".csv";
 downloadLink.download =  fileName; 
 document.body.appendChild(downloadLink);
 downloadLink.click();
 document.body.removeChild(downloadLink); 

Blob对象简要介绍

Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 Blob 的功能并将其扩展使其支持用户系统上的文件。

语法
const aBlob = new Blob( array, options );

参数说明

array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8。
options 是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性:
type,默认值为 “”,它代表了将会被放入到blob中的数组内容的MIME类型。
endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: “native”,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 “transparent”,代表会保持blob中保存的结束符不变

URL.createObjectURL() 与介绍

URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。相当于这个方法创建了一个传入对象的内存引用地址

参考原理剖析:前端通过Blob实现文件下载
参考流程:JS知识点:文件下载

项目常用方式:
压缩包,word文件等普通下载

   preview(url) {
	   // window.open(url);
      let a = document.createElement("a");
      a.style.display = "none";
      a.target = "_blank";
      document.body.appendChild(a);
      a.href = url;
      a.setAttribute("download", "link"); // 指示浏览器下载url,而不是导航到它
      a.click();
      document.body.removeChild(a);
   },

图片 音频等会被浏览器直接打开的下载:

    downloadFile(url,name){    
      var a = document.createElement('a');
      // 先将地址转化为二进制
      var blob = new Blob([url]);
      a.href = URL.createObjectURL(blob);
      // 剪切链接字符串最后的文件名称
      // debugger
      a.download = name;
      a.click();
      document.body.removeChild(a);
    },

批量下载

//  批量下载
        downloadFile(url){
          const iframe = document.createElement("iframe");
          iframe.style.display = "none";  // 防止影响页面
          iframe.style.height = 0;  // 防止影响页面
          iframe.src = url;
          document.body.appendChild(iframe);  // 这一行必须,iframe挂在到dom树上才会发请求
          // 5分钟之后删除(onload方法对于下载链接不起作用,就先抠脚一下吧)
          setTimeout(()=>{
            iframe.remove();
          }, 5 * 60 * 1000);
        },

        bulkDownload(urlList){
          let jsonUrlList = JSON.parse(urlList);
          let that = this;
          for(let i =0;i<jsonUrlList.length;i++){  //循环遍历调用downloadFile方法
            const url = jsonUrlList[i].response.msg;
            this.downloadFile(url);
          }
        },

终极解决方案 使用canvas下载


const handleDownload = (url) => {
    const img = new Image()
    img.crossOrigin = "anonymous"; //非同源避免污染
    let name;
    if(url==undefined){
        img.src = dataForm.data.cover
        name = dataForm.data.cover.slice(dataForm.data.cover.indexOf('images')+7); 
    }else{
        img.src = url.url
        name = url.name
    }
    img.onload = () => {
        const canvas = document.createElement('canvas')
        canvas.width = img.width
        canvas.height = img.height
        const ctx = canvas.getContext('2d')
        ctx.drawImage(img, 0, 0)
        canvas.toBlob(blob => {
            const url = URL.createObjectURL(blob)
            const link = document.createElement('a')
            link.href = url
            link.download = name
            document.body.appendChild(link)
            link.click()
            document.body.removeChild(link)
            URL.revokeObjectURL(url)
        })
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

跳动的世界线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值