JQuery调用Servlet实现文件下载

web页面实现文件下载的几种方法

今天碰到文件下载的一些问题,本着知其然也要知其所以然的精神,站在巨人的肩膀上深入学习和测试了一下,抛砖引玉,现在总结结论如下:

1)标准URL下载方式 可以通过在web页面中嵌入 url超级链接,标准的HTTP GET请求,形如:“http://www.wjj.cc/test.zip” 的方式来下载。对于服务器端web根目录有一个test.zip的文件。不解释了,傻子都明白,看不明白就也没有必要去搞IT了。 说明:此种方法的弊端是完全暴露了文件test.zip的网站路径,而且动态性不够灵活。网上已经很多资料,不多说了。

 

2)通过服务器端脚本向浏览器方(stdout)输出二进制流的方式下载。比如 html页面中嵌入URL为:http://www.wjj.cc/download.php&f=test.zip ,此方法是GET方式请求,URL完全可以获取到。 说明:上述方法可以在服务器端 通过 脚本程序 download.php ,并且根据传入的查询字符串f=test.zip定位服务器上文件系统test.zip的路径,然后按二进制流的方式发送给客户端浏览器,那么客户端浏览器就会弹出一个“下载对话框”了。 另一种方式是通过 提交表单,用POST方式提交参数到服务器端动态脚本,然后服务器端脚本返回输出的二进制流到浏览器实现下载。尤其是当需要下载的文件(可能不一定是服务器上文件系统中具体的文件,有可能是服务器动态生成的数据) 依赖于客户端提交的很多参数选项的时候,采用POST下载的方式是最多的。

下面重点讲述通过动态脚本实现下载的一些例子,下面的例子中均没有给出服务器端动态脚本的处理代码:

1. GET URL下载链接,可以直接嵌入到 <a href="URL...">下载</a> 。 2. POST的URL下载链接,可以通过设置<form>表单的action 以及 表单元素值来完成下载3. 如果是GET方式的url下载链接,客户端可以通过一个动态生成的隐藏的iframe来得到下载的二进制文件。原理是:iframe有一个src属性,其本质就是发送http请求,GET一个页面或者数据。javascript如下: function download(){             var IFrameRequest=document.createElement("iframe");             IFrameRequest.id="IFrameRequest";             IFrameRequest.src="/test.zip";             IFrameRequest.style.display="none";             document.body.appendChild(IFrameRequest); }

4. 用动态生成的form元素,实现表单提交,开完成下载。注意:此方法不是ajax哦。 参考url:http://www.cnblogs.com/sydeveloper/archive/2013/05/14/3078295.html 要说明的是,这里的原理仅仅是form提交表单,而不是ajax。

 由于jQueryajax函数、及ajaxSubmit等函数的返回类型(dataType)只有xmltextjsonhtml等类型,没有“流”类型,故我们要实现ajax下载时,不能够使用相应的ajax函数进行文件下载。

         在网上看了一些文章,发现可以通过js生成一个form,用这个form提交参数,并返回“流”类型的数据。在实现过程中,页面也没有进行刷新。

请看实例:

var form = $("<form>");   //定义一个form表单

       form.attr('style','display:none');   //下面为在form表单中添加查询参数

       form.attr('target','');

       form.attr('method','post');

       form.attr('action',"exportSms");

      

       var input1 = $('<input>'); 

       input1.attr('type','hidden'); 

       input1.attr('name','exportPostTime'); 

       input1.attr('value',timeString); 

      

       $('body').append(form);  //将表单放置在web中

       form.append(input1);   //将查询参数控件提交到表单上

       form.submit();   //表单提交

 

 

jsp页面上的txt附件,点击后浏览器默认直接打开,结果是乱码。

因为用户上传的txt文件可能是ANSI、Unicode、UTF-8编码的任意一种,上传时后台获取文件内容重写一遍保证浏览器打开正常太过麻烦,

同时也觉得下载到本地更为合适,所以希望实现点击下载。

最初的实现方式是在Web.xml中配置mime-type,如下:

<mime-mapping>  <extension>txt</extension>  <mime-type>application/txt</mime-type> </mime-mapping>

但是最后发现在IE6上无效,仍然是直接打开,只好寻求新的方法。最后使用如题的方式解决,参考了

http://www.cnblogs.com/sydeveloper/archive/2013/05/14/3078295.html这里的文章。

代码如下:

页面js:下面是我工程中实际用到的:其中fnDownLoadJsonFile为button的onclick调用的函数,tbl为button所在的容器,此处为table.

 function fnDownLoadJsonFile(tbl){

            var $json_dir=$(tbl).parents('tr').children('td');
            var jsonfiledir=$json_dir.eq(1).text();
            var filenames;
            filenames=jsonfiledir.split("/");
            var filename=filenames[filenames.length-1];

            var uri="../NetworkServlet?ActionId=7&JsonFileDir="+jsonfiledir;
/
            downFile(jsonfiledir);

            return;

        }

        function downFile(filePath){
            var form=$("<form>");//定义一个form表单
            form.attr("style","display:none");
            form.attr("target","");
            form.attr("method","post");
            form.attr("action","../NetworkServlet?ActionId=7");
            var input1=$("<input>");
            input1.attr("type","hidden");
            input1.attr("name","JsonFileDir");
            input1.attr("value",filePath);
            $("body").append(form);//将表单放置在web中
            form.append(input1);
            form.submit();//表单提交
            form.remove();
        }


Java servlet :

private void doActionDownLoadFileJson(HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        // TODO Auto-generated method stub
        Context ctx = (android.content.Context) conf.getServletContext()
                .getAttribute("org.mortbay.ijetty.context");

        String mJsonFileDir;
        mJsonFileDir = request.getParameter("JsonFileDir");
        String filenames[] = mJsonFileDir.split("/");
        String filename = null;
        if (filenames.length > 1) {
            filename = filenames[filenames.length - 1];
        }

        // 设置下载的类型 告诉浏览器 需要以下载的方式操作
        response.setContentType("application/force=download");
        // 下载头设置
        response.setHeader("content-disposition", "attachment;fileName="
                + java.net.URLEncoder.encode(filename, "UTF-8"));

        File file = new File(mJsonFileDir);
        // 创建输入流对象
        java.io.FileInputStream fileInputStream = null;
        ServletOutputStream sos = null;
        PrintWriter writer = null;
        
        try {
            fileInputStream = new java.io.FileInputStream(file);
            writer = response.getWriter();
//            response.getOutputStream();
            int i;
            while ((i = fileInputStream.read()) != -1) {
                writer.write(i);
            }
            writer.flush();
            
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (sos != null) {
                try {
                    sos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (writer != null) {
                writer.close();
            }
        }

        return;

    }

里面用的服务器为Jetty app服务器.兼容多个浏览器....

 

其中有两点需要注意:

<1> : 第一点就是jquery的ajax不支持下载文件,上面红色处已表明;

<2> : 后台的getOutStream是不能够使用的,否则会和文件流冲突;

 

 

posted @ 2014-03-04 14:42  MMLoveMeMM  阅读(4666)  评论(0编辑  收藏  举报