【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>  '; 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令牌才能进行下载,
否则下载失败
1 2 3 4 5 6 7 8 9 10 11 12 13 | $( '#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; } ); }); |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步