【JavaScript】文件上传下载问题

问题原因

一般文件上传前端甚至可以不涉及JS来实现

input标签套在form标签,由form标签直接发送请求就可以实现上传功能

但是现在很多项目都使用前后端分离,AJAX一刀切所有。

input标签没有form表单标签支持,文件上传也要走AJAX完成

两种实现方案

1、基于FormData实现,利用JS封装成FormData参数来请求

2、利用JS的FileReader转码成Base64字符串参数来请求

关于Input中的File对象

https://blog.csdn.net/weixin_30617797/article/details/95833917

怎么获取到文件本身在JS中是被屏蔽的

但是能够提供一些基本信息:

1、文件名称 name

2、文件大小 size 以字节计算

3、文件类型 type

项目中的方案:

文件上传的标签是需要动态添加的

// 添加附件
$addAttachment.on('click', function() {
    let imgLimit = 6;
    if ($('#attachment').children().length == imgLimit) {
        mui.alert("超过PDI上传限制!(" + imgLimit + ")");
        return;
    }
    let inputHtmlCode = ''; 
    inputHtmlCode += '<div style="display: flex; justify-content: space-between;padding:5px;margin-top:5px;overflow: scroll;">';
    inputHtmlCode += '    <button type="button" func="del" class="mui-btn mui-btn-red delItem" style="display: block;">删除</button> &#12288;';
    inputHtmlCode += '    <input type="file" style="box-sizing: border-box;">';
    inputHtmlCode += '</div>';
    $('#attachment').append(inputHtmlCode);
});

删除文件就直接移除DOM

// 删除附件
$('#attachment').on('click','.delItem', function() {
    // $(this).parent().remove();
    let $thisObj = $(this);
    mui.confirm(
        '是否取消此文件上传?',
        '取消上传',
        ["否", "是"],
        function (btnArr) {
            if (btnArr.index == 1) $thisObj.parent().remove();
        }
    );
});

对上传的文件设置大小限制:

清空value属性即重置了文件选择

// 监听附件大小控制
$('#attachment').on('change','[type="file"]', function(event) {        
    let selectedFile = event.target.files[0];
    let maxSizeLimit =  1024 * 1024 * 60; // 60m
    if (selectedFile.size > maxSizeLimit) {
        mui.alert('超过60M文件大小限制!');
        this.value = '';
    }
    
    // console.log('文件大小/字节:' + f.size);
    // console.log('文件名称:' + f.name);
    // console.log('文件类型:' + f.type);
});    

新需求,不允许重复上传:

// 监听附件大小控制 和文件相同限制
$('#attachment').on('change','[type="file"]', function(e) {    
    // mui.alert('监听触发');
    let thisIndex = $(this).index();
    let file = e.target.files[0]; 
    let maxSizeLimit = 1024 * 1024 * 60; // 60m
    if (file.size > maxSizeLimit) {
     mui.alert('超过60M文件大小限制!');
     file.value = '';
     return;
    } 
    var _self = this;
    var fileList= document.getElementsByClassName("file");
    if(fileList && fileList.length > 0){
        for(var i = 0 ; i < fileList.length ; i++){
            var x =  fileList[i];
            if(x.getAttribute("fileName") == file.name){
                this.value = "";
                return mui.alert("上传的文件名不能相同");
            }
        }
    }
    
    if(e.target.files[0]){
        this.setAttribute("fileName" , e.target.files[0].name);
        this.setAttribute("class" , "file");
    }
});

 

 

 

最后是提交请求:

1、要创建一个formData对象,把input标签的首个文件对象入参,

2、Key键是根据接口的要求来写的,一般默认叫【file】

3、然后AJAX的contentType类型要设置【multipart/form-data】

接口是单个文件上传,如果要多个文件,就遍历请求

后台是把文件送到文件服务器上,fastdfs, 然后会返回服务器存储地址和文件名称

再把这个路径送到常规后台写入数据库中

$('#testing').on('click', function() {
    // 封装报告附件参数
    $('[type="file"]').each(function(index, element){
        if (element.value != '') {
            let thisFile = element.files[0];
            let formData = new FormData();
            formData.append("dmsFile", thisFile);
            $.ajax({
                url : dms.getServerIp() + dms.getDmsPath()["dcsfactorybase"] + "factoryBase/fdfsfile/upload" ,
                data: formData,
                async: false,
                dataType: 'json', //服务器返回json格式数据
                contentType: 'multipart/form-data',
                type: 'POST', //HTTP请求类型
                timeout: 30000, //超时时间设置为30秒;
                contentType: false,
                processData: false,
                headers:{ 'jwt': localStorage.getItem("urlToken") },
                success: function(res) {
                    console.log("执行请求成功 url: " + dms.getServerIp() +  dms.getDmsPath()["appiJmc"] + "/licensePlate");
                },
                error: function(xhr, type, errorThrown) {
                    // console.log("执行请求失败 url: " + dms.getServerIp() +  dms.getDmsPath()["appiJmc"] + "/licensePlate");
                }
            });
        }
    }); 
    
});

BASE64转码方案:

首先还是要选中到file文件对象

创建JS的一个文件读取对象

readAsDataUrl方法能够在文件对象中读取文件内容

然后重写onloaded方法,result就是文件的bas64编码

let selectedFile = event.target.files[0];
// let fileReader = new FileReader();
// fileReader.readAsDataURL(selectedFile);
// fileReader.onloadend = function (e) {
//     console.log('文件编码 ->' +  e.target.result);
// }

AJAX请求头还需要设置:

"Content-Type": "application/x-www-form-urlencoded"

 

 文件下载:

一般后台接口返回的是一个响应的文件流对象

这个时候不要再用AJAX处理了,交给浏览器跳转解析就能实现

这会导致一些问题:

1、接口必须是GET请求

2、参数必须在地址中

在项目中的下载案例:

这里接口还而外要求提供JWT令牌才能进行下载,

否则下载失败

$('#attachment').on('click', '[type="button"]', function() {
    let thisJqDom = $(this);
    mui.confirm(
        '是否要下载?\n【' + thisJqDom.text() + '】',
        '下载文件',
        ["否", "是"],
        function(btnList) {
            if (btnList.index != 1) return;
            let jwt = localStorage.getItem("urlToken");
            window.location.href = dms.getServerIp() + dms.getDmsPath()["dcsfactorybase"] + "factoryBase/fdfsfile/downfilebykey" + '?key=' + thisJqDom.attr('link') + '&fileName=' + thisJqDom.text() + '&jwt=' + jwt;
        }
    );
});

  

 

  

 

posted @ 2021-04-11 11:19  emdzz  阅读(148)  评论(0编辑  收藏  举报