解决页面下载文件,资源不存在页面出现空白的问题。

来源:互联网 发布:程序员离职前放木马 编辑:程序博客网 时间:2024/05/25 19:58

框架和环境:ssm+maven3.0+db2+easyui1.4+jdk1.7

功能背景:第一步是通过定时轮询把封闭系统请求的入参报文生成文件放到共享盘的目录。同时把文件的路径信息存到数据库表。第二步就是我这个页面的功能,把生成的文件信息列表显示并可以选中下载文件列表。但是发现如果这个文件已经删除,点击下载后由于资源不存在后台异常,虽然做了处理,但是页面就会出现空白。

实现页面文件下载的思路:查询的时候把每个文件的路径也查出来,在页面进行隐藏,等到下载的时候把文件对应路径传到后台,后台依据这个路径可以找到文件,并读取写到页面,实现下载功能。

1.页面点击下载触发的方法。主要同过window.location.href=“”来进行链接方式下载。之前的博文有介绍post方法无法完成文件下载。

function downloadOrderExport(){    var row=$("#dataTable").datagrid('getSelected');       if(row !=null){        var filepath=escape(encodeURIComponent(row.filePath));        window.location.href=basePath+"/orderExport/downloadAndUpdate?filePath="+filePath;    }else{        $.messager.alert('提示','请选择一条你要下载的记录!');    }}

2.具体Controller层的方法为void,这也是不同于StringL类型返回值的最大区别和难点。由于无法用return,只能用response转跳到另一个Controller,然后返回页面:

@RequestMapping("/download")    public void downloadXmlFile(HttpServletRequest request,HttpServletResponse response){        String filePath=request.getParameter("filePath");        //为防止文件名乱码,这里进行处理        try {            filePath=URLDecoder.decode(filePath,"utf-8");        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }        File file=new File(filePath);        String fileName=file.getName();        try{            InputStream fis=new BufferedInputStream(new FileInputStream(filePath));            byte[] buffer=new byte[fis.available()];            fis.read(buffer);            fis.close();            //清空response            response.reset();            //设置response的Header            response.setHeader("Content-Disposition","attachment;filename="+new String(fileName.getBytes()))            response.setHeader("Content-length",""+file.length());            OutputStream toClient=new BufferedOutputStream(response.getOutputStream());            response.setContentType("application/octet-stream");            toClient.write(buffer);            toClient.flush();            toClient.close();        }catch(Exception e){            logger.error("文件下载出错。"+e.getMessage(),e);            //文件不存在时会在FileinputStream(filePath)读取时异常,进入这里。导致前台页面无响应。这里就进行重定向到原页面,并带上错误标记            try{                //request.getCOntextPath()获取项目名,这个必须加上,不然找不到对应path的方法。页面404,这个path对应本类的另一个方法(在下面有)                response.sendRedirect(request.getCOntextPath()+"/orderExport/toOrderExport?error=error");            }catch(IOException e1){                logger.error(e1);            }        }    }    //转跳到下载的主页面    @RequestMapping("/toOrderExport")    public String jumpToOrderExportJsp(){        return "/orderExport/orderExportIndex";    }

3.经过前两步,如果要下载的文件有异常,就会进入异常处理模块—通过response请求转发到前台下载页面。但是问题来了:我们是通过window.location.href进行后台。并没有回调函数的功能,该如何接收后台的入参呢?答案是在页面每次加载时进行异常标记的判断!js代码如下:

$(function(){    function getQueryString(param){        var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");        var r = window.location.search.substr(1).match(reg);        if(r!=null){            $.messager.alert('提示','你下载的文件不存在!');        }     }    getQueryString("error");})

总结:

1.针对重定向-redirect在ssm的controller层使用分为两种:一种是方法有返回值,一般为String,重定向用return “请求地址”即可;另一种方法是无返回值void,只能用response.sendRedirect(request.getContextPath+”请求地址”)
针对String类型的重定向,这篇博文:spring mvc controller间跳转 重定向 传参讲的比较清楚。分带参数和不带参数两种。


2.正常的从后台我们拿到的都是集合,map等,但是接触后台重定向请求前台的很少,带参数返回前台的就更少/orderExport/toOrderExport?error=error。我这里就是获取个标记,只要error不为空就证明出现异常。那么正常情况下该如何获取后台的请求参数呢?这里有两种方法供选择。一种是正则方法,一种是传统截取的方法。推荐使用第一种。我这里参考博文:获取参数的方法

方法一:采用正则表达式获取地址栏参数:( 强烈推荐,既实用又方便!)

function GetQueryString(name){     var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");     var r = window.location.search.substr(1).match(reg);     if(r!=null){        return  unescape(r[2]);      }    return null;}// 调用方法,获取指定参数名的参数值alert(GetQueryString("参数名1"));alert(GetQueryString("参数名2"));alert(GetQueryString("参数名3"));

下面举一个例子:

若地址栏URL为:abc.html?id=123&url=http://www.maidq.com

那么,但你用上面的方法去调用:alert(GetQueryString(“url”));

则会弹出一个对话框:内容就是 http://www.maidq.com

如果用:alert(GetQueryString("id"));那么弹出的内容就是 123 啦;

当然如果你没有传参数的话,比如你的地址是 abc.html 后面没有参数,那强行输出调用结果有的时候会报错:
所以我们要加一个判断 ,判断我们请求的参数是否为空,首先把值赋给一个变量:

var myurl=GetQueryString("url");if(myurl !=null && myurl.toString().length>1){   alert(GetQueryString("url"));}

这样就不会报错了!

方法二:传统方法

<script type="text/javascript">function UrlSearch() {   var name,value;    var str=location.href; //取得整个地址栏   var num=str.indexOf("?")    str=str.substr(num+1); //取得所有参数   stringvar.substr(start [, length ]   var arr=str.split("&"); //各个参数放到数组里   for(var i=0;i < arr.length;i++){     num=arr[i].indexOf("=");     if(num>0){      name=arr[i].substring(0,num);     value=arr[i].substr(num+1);     this[name]=value;     }     } } var Request=new UrlSearch(); //实例化alert(Request.id);</script>
阅读全文
0 0