踩坑记

由于某些原因,不能粘贴代码,那就记录整个过程吧,没有经验,一个坑一个坑的踩!

代码都是手敲的,条件不允许不能复制粘贴,我检查过了没问题。

前端请求后端浏览器下载,记得不能有返回值!!!

一、文件上传(EasyUI+SpringBoot)

1、先是获取文件路径的时候,不管你从什么目录上传,前端获取到的都是"C:\fakepath\"目录,说这是ie8下的安全设置问题,怎么解决百度上有;

2、客户端上传文件到服务器端,用form表单提交,之前写好的代码不想重写,所以模拟from表单进行提交,js模拟form表单,后端用@RequestParam("file") MultipartFile file来接收,然后前端没问题拿到了文件,然后怀疑是不是不是用这个来接收文件的吧,查看老项目源码,就是这个来接收,前后端都没问题,但就是后端拿不到,最后只能新建个简单的页面用真实的form表单提交,确实可以获取到;

3、form表单提交前要对表单数据进行验证,可在form表单上添加οnsubmit="return check()",注意return,return true提交,return false则不提交;

4、form表单提交后,如何获取后端的返回值判断有没有成功?网上说的大部分都是添加jquery-form.js,有的说是添加jquery.form.js,局域网开发,我还得先确定到底是哪个,本地没有的话还得申请,由专人负责下载入网,太麻烦了。幸好找到了办法:

form表单默认的提交是没有返回值的,而且默认提交成功之后是跳转,跳转的action的路径,下面写一下默认的提交如何获取到form表单的返回值json,并且阻止默认的跳转动作。

<form target="form" action="xxx" enctype="multipart/form-data" method="post">

     <input type="file">

     <button type="submit" id="submit" style="display:none">提交</button> 

</form>

<iframe name="form" id="form" style="display:none"></iframe>

<-iframe的隐藏内联框架,我们的form表单的target属性值等于这个iframe的name和id,那么我们就可以用iframe来接收返回值,并且把默认的跳转让iframe去跳转,下面的代码,来获取这个返回值json。->

$("#submit").click();

$("#form").load(function(){

    //$("#submit").click();//提交完form表单,下面的代码可以获取到返回值

    var text = $(this).contents().find("body").text();  //获取到的是json的字符串

    var data = $.parseJSON(text);   //json字符串转换成json对象

    console.log(data); //注意,只要这个iframe框架加载完成就说明发送成功了。

});

5、这次实现的是数据、文件动态提交,form表单的话,表单中有多少项也不确定,后端没办法接收值,这次采用ajax模拟form表单。 

//1、创建FormFata
var formData = new FormData() ; 

//2、FormData下有一个append的属性,是用来存储需要传递到后盾的数据,第一个参数是后端定义的字段key值,第二个值是你需要传递的参数
//多文件上传的话,第二个参数接收一个对象,不能接收文件数组,可以使用for循环,key值一样,val是需要上传的文件对象;如果是字符串数组的话,试了可以,文件数组的话不行。
formData.append(key,val) ;

$.ajax({
     type:"post",
     url:"/xxxx/xxx",
     data:formData,
    //3、cache、processData、contentType这三个属性如果使用formDate+ajax模拟表单上传的时候必须要进行配置
    //这三个属性必须设置,当模拟form表单提交时,forData自带属性,如果这三个属性有true,则会按ajax传统方式上传

      //不读取缓存中的结果 true的话会读缓存  其实post本身就不会读取缓存中的结构
      cache: false,
      //默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。
      processData: false,
      //数据编码格式不使用jquery的方式 为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。
      contentType: false,
      success:function (res){
            
      }
}) 

二、多文件上传、下载 

1、多文件上传,multiple表示多文件上传,<input type="file" multiple name="file"/>

2、多文件上传,Tomcat默认最大1M,SpringBoot 2.0之后这样配置:

spring.servlet.multipart.enabled = true;

spring.servlet.multipart.max-file-size = 2000MB;      单文件最大范围

spring.servlet.multipart.max-request-size = 2000MB;     多文件总的最大范围 

3、多文件js下载,window.open(url)放到循环中只会下载一次,浏览器把它当成弹窗广告拦截了。遇到txt、jpg、png浏览器能打开的不会当成文件处理,直接 就打开了。网上现在大多都是抄过来,自己不试也不改,我们局域网又不能复制粘贴,只能手敲,找了很久才找到这个可以用,就是txt直接打开,图片没反应是因为这个为了防止浏览器拦截每次都是创建一个iframe,对图片不适用。

for(var i=0; i<result.length; i++){
    download(url + result[i]);
}

//多文件循环下载
function download(url){
    var elemIF = document.createElement("iframe");
    elemIF.src = url;
    elemIF.style.display = "none";
    document.body.appendChild(elemIF);
}

 三、多文件下载浏览器拦截问题

通过window.open("xxxxxx")直接访问文件地址,浏览器会默认进行下载,但是浏览器能打开的,比如txt,jpg,png等浏览器默认就打开了,还存在一个问题就是如果想多文件下载,把window.open("xxxxxx")放到循环中,浏览器只会下载一次,是因为window.open("xxxxxx")打开新页面,并且放到循环中,浏览器以为是弹窗广告,所以就给拦截了,只允许一次。网上找办法,试了没用,也不知他们怎么试的,好多都一样。既然这样,那我们还是放到后端浏览器默认下载吧。

IO流下载都差不多,这是设置响应头浏览器默认地址下载,其他浏览器弹框等可以看另一篇博客,都差不多。

1、前端部分重要代码

//下载附件
function look(){
	var text = document.getElementByName("fxkname");
	var result = [];//存放所有被选中的复选框的值
	for(k in text){
		if(text[k].checked){
			result.push(text[k].value);
		}
	}
	//循环请求后端下载,ajax请求没反应,得用window.location.href或者window.open,
        //但是多文件下载,循环中还是会被拦截的,那我们就新建iframe来循环请求
	for(var n=0;n<result.length;n++){
		download("xxxxxx?file=" + result[n]);
	}
}

//防止浏览器当广告拦截
function download(url){
	var elemIF = document.createElement("iframe");
	elemIF.src = url;
	elemIF.style.display = "none";
	document.body.appendChild(elemIF);
}

2、后端部分重要代码

        /**
	 * 浏览器下载文件
	 * @param response
	 * @param fileName 文件名 + 后缀名
	 * @param path 存放文件的地址
	 */
	public static void downloadFile(HttpServletResponse response,String fileName,String path) {
		
		String filename = fileName.substring(0,fileName.lastIndexOf("."));//文件名
		String suffix = fileName.substring(fileName.lastIndexOf("."));//后缀名
		
		try(
                    InputStream inputStream = new FileInputStream(path + fileName);
		    ServletOutputStream outputStream = response.getOutputStream()) {
			response.setContentType("application/x-download;charset=utf-8");
			response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(filename,"UTF-8")+suffix);
			
			byte[] buffer = new byte[1024];
			int len = 0;
			while ((len = inputStream.read(buffer)) != -1) {
				outputStream.write(buffer,0,len);
			}
			outputStream.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
	}

3、EasyUI弹框父子页面问题 

三种:1、window(窗口)(使用中);2、dialog(对话框窗口);3、messager(消息窗口)

<--父页面-->
<div id="win"></div>

$('#win').window({
    width:330,
    height:220,
    modal:true,
    title:'win弹框',
    onClose:function(){ //关闭子页面触发此事件
        show(); //显示刷新父页面表格
    }
});

$('#win').window('refresh','editor.html');

function fcz(){
    return '要传给子页面的参数';
}

<--子页面-->
var result = parent.window.fcz(); //调用父页面方法获得参数

四、dom4j生成xml并下载 

//生成xml的文件名
private final String TABLE_NAME = "xxxx";
@Autowired
private HttpServletResponse response;

public void createXml(){
    //使用dom4j生成xml文件
    Document doc = DocumentHelper.createDocument;
    Element root = doc.addElement("Root_GK");
    for(int i=0;i<list.size();i++){
        Element emp = root.addElement("GK");
        //给节点添加属性
        emp.addAttribute("AAA","XXX");
        emp.addAttribute("BBB","XXX");
        emp.addAttribute("CCC","XXX");
        emp.addAttribute("DDD","XXX");
    }
    //浏览器下载
    DownloadUtils.downloadXml(response,TABLE_NAME,doc);
}

/**
* 浏览器下载xml
* @param response
* @param tableName 要生成的xml名
* @param doc 生成xml的节点
*/
public static void downloadXml(HttpServletResponse response,String tableName,Document doc) {
	PrintWriter writer = null;
	XMLWriter xw = null;
		
	try {
		response.setContentType("application/xml;charset=utf-8");
		response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(tableName,"UTF-8")+".xml");
		writer = response.getWriter();
			
		OutputFormat opf = OutputStream.createPrettyPrint();
		opf.setEncoding("UTF-8");
		xw = new XMLWriter(writer, opf);
		xw.write(doc);
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		try {
			if(xw != null) {
				xw.close();
			}
			if(writer != null) {
				writer.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
		
}

所有浪费了的日子都是要还的,要么以后加班还,要么承受相应的代价。

选择是要付出代价的,这个代价必须有人来承受。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值