• 【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(
            '是否要下载?
    【' + 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;
            }
        );
    });
    

      

      

  • 相关阅读:
    hdu1159 LCS模板题
    RabbitMQ入门
    Dubbo
    SpringMVC
    MySQL的再理解
    ElasticSearch
    redis入门学习
    Swagger
    SSM整合
    MybatisPlus
  • 原文地址:https://www.cnblogs.com/mindzone/p/14643233.html
Copyright © 2020-2023  润新知