jsp中实现文件下载的最简单的方式是在网页上做超级链接,如:<a href="music/abc.mp3">点击下载</a>。但是这样服务器上的目录资源会直接暴露给最终用户,会给网站带来一些不安全的因素。因此可以采用其它方式实现下载,可以采用:

1、RequestDispatcher的方式进行;

2、采用文件流输出的方式下载。

1、采用RequestDispatcher的方式进行

jsp页面中添加如下代码:

        <%
response.setContentType("application/x-download");//设置为下载application/x-download
String filedownload = "/要下载的文件名";//即将下载的文件的相对路径
String filedisplay = "最终要显示给用户的保存文件名";//下载文件时显示的文件保存名称
filenamedisplay = URLEncoder.encode(filedisplay,"UTF-8");
response.addHeader("Content-Disposition","attachment;filename=" + filedisplay); try
{
RequestDispatcher dis = application.getRequestDispatcher(filedownload);
if(dis!= null)
{
dis.forward(request,response);
}
response.flushBuffer();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{ }
%>

2、采用文件流输出的方式下载

         <%@page language="java" contentType="application/x-msdownload"    pageEncoding="gb2312"%><%
//关于文件下载时采用文件流输出的方式处理:
//加上response.reset(),并且所有的%>后面不要换行,包括最后一个; response.reset();//可以加也可以不加
response.setContentType("application/x-download");
String filedownload = "想办法找到要提供下载的文件的物理路径+文件名";
String filedisplay = "给用户提供的下载文件名";
filedisplay = URLEncoder.encode(filedisplay,"UTF-8");
response.addHeader("Content-Disposition","attachment;filename=" + filedisplay); OutputStream outp = null;
FileInputStream in = null;
try
{
outp = response.getOutputStream();
in = new FileInputStream(filenamedownload); byte[] b = new byte[1024];
int i = 0; while((i = in.read(b)) > 0)
{
outp.write(b, 0, i);
}
outp.flush();
}
catch(Exception e)
{
System.out.println("Error!");
e.printStackTrace();
}
finally
{
if(in != null)
{
in.close();
in = null;
}
if(outp != null)
{
outp.close();
outp = null;
}
}
%>

此处中文名字容易出现乱码:可改成 new String(file_name.getBytes("gb2312"),"iso8859-1")

在wsad里面写JSP文件下载,总是出现这个异常,getOutputStream() has already been called for this response,输出流已经被调用了.

上网查半天终于明白一点,JSP早下载文件的时候用到了OutputStream,而在Application Server在处理编译jsp时对于%>和<%之间的内容一般是原样输出,而且默认是PrintWriter.

对于第二种方法,我认为应该是比较常用的。不过有几个地方是值得我们注意的:

一、采用第二种方法的主要优点是实际文件的存放路径对客户端来说是透明的。 
这个文件可以存在于任何你的服务器能够取得到的地方,而客户端不一定能直接得到。例如文件来自于数据库或者内部网络的一个FTP服务器。还句话说,这种方式可以实现隐藏实际文件的URL地址。

二、为了防止客户端浏览器直接打开目标文件(例如在装了MS Office套件的Windows中的IE浏览器可能就会直接在IE浏览器中打开你想下载的doc或者xls文件),你必须在响应头里加入强制下载的MIME类型: 
response.setContentType("application/force-download");//设置为下载application/force-download 
这样,就可以保证在用户点击下载链接的时候浏览器一定会弹出提示窗口来询问你是下载还是直接打开并允许你选择要打开的应用程序,除非你设置了浏览器的一些默认行为。 
或者,你想让客户端自行处理各种不同的文件类型,你可以在服务器的配置文件中配置MIME类型映射,通过简单的判断文件后缀名来处理。例如,在Tomcat中设置MIME响应类型: 
如果文件在客户端中的响应程序类型和期望不一致,修改$TOMCAT_HOME\conf\web.xml文件中的如下部分 : 
<mime-mapping> 
  <extension>zip</extension> 
  <mime-type>application/zip</mime-type> 
</mime-mapping> 
<mime-mapping> 
  <extension>mht</extension> 
  <mime-type>message/rfc822</mime-type> 
</mime-mapping> 
……

三、在响应头中尽量不要设置浏览器缓存期限。 
有时候用户在点击了下载链接后,在弹出窗口中,用户想直接点击“打开”,而不想保存到指定路径。这时候如果我们在响应头中限制了不允许使用浏览器缓存(即总是刷新),在IE浏览器中我们将无法直接打开该文件。因为限制了不允许使用缓存,浏览器无法将文件保存到临时文件夹(即缓存)。 
也就是说,在响应头中不要进行如下的设置(已注释): 
  //response.addHeader("pragma","NO-cache"); 
  //response.addHeader("Cache-Control","no-cache"); 
  //response.addDateHeader("Expries",0);

四、文件名为中文或其他unicode字符时的处理。 
有时候提供下载的文件名中包含中文字符或者其他unicode字符,会导致浏览器无法正确的采用默认的文件名保存文件。我们应该记住在响应头中包含filename字段并采用ISO8859-1编码(推荐)或者采用UTF-8编码: 
response.setHeader("Content-disposition","attachment; filename="+new String(filename.getBytes("UTF-8"),"iso8859-1")); //采用ISO8859-1编码 
response.setHeader("Content-disposition","attachment; filename="+URLEncoder.encode(filename, "UTF-8")); //采用UTF-8编码 
但是,这种方式在不同的浏览器中表现也有所不同。例如在IE和Firefox中,采用ISO8859-1编码可以正确显示文件名,而在Opera中不管采用那种编码,默认保存的文件名都无法做到正确显示。 
所以最好的方法其实就是尽量在文件名中使用ascii编码。

五、由于采用流的方式进行输入输出,我们必须保证在使用完毕后关闭流的资源。 
一般我们把关闭流的操作放在finally块中,以保证在程序段结束前一定会关闭流的资源:

InputStream is = null;
ServletOutputStream sos = null;
try {
is = ...; //通过某种方式读进数据到输入流
sos = response.getOutputStream(); //打开输入流
byte[] buff = new byte[2048];
int bytesRead;
while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
sos.write(buff,0,bytesRead);
sos.flush();
}
} catch(IOException ex) {
//TODO something with IOException
} catch(Exception ex) {
//TODO something with Exception
} finally {
if(is != null) {
is.close(); //关闭输入流
}
if(sos != null) {
sos.close(); //关闭输入流
}
}

jsp中文件下载的实现的更多相关文章

  1. jsp实现文件下载,out = pageContext.pushBody();out.close();不用写到jsp中

    测试jsp: <%@ page contentType="text/html; charset=gbk" %> <% try{ com.enfo.intrust. ...

  2. jsp中实现点击文件名称完成下载

    1.文件名称添加点击事件 <a href="javascript:void(0);" id="wjm" onclick="wjxz();&quo ...

  3. java后台json如何传递到jsp中解析

    需求:  系统前端jsp使用的是easyUi的datagrid展示了一些任务信息,任务信息中有个状态信息显示的值是数字, 需要根据后台保存的映射关系,将状态显示为描述信息. 原来的jsp前端显示: 解 ...

  4. 浅谈JSP中include指令与include动作标识的区别

    JSP中主要包含三大指令,分别是page,include,taglib.本篇主要提及include指令. include指令使用格式:<%@ include file="文件的绝对路径 ...

  5. java web学习总结(二十八) -------------------JSP中的JavaBean

    一.什么是JavaBean JavaBean是一个遵循特定写法的Java类,它通常具有如下特点: 这个Java类必须具有一个无参的构造函数 属性必须私有化. 私有化的属性必须通过public类型的方法 ...

  6. jsp中的@include与jsp:include区别详解

    1 前言 搞java开发的人也许都知道在jsp中引入项目中其他文件有如下两种方式 <%@include file="xxx.jsp"%> <jsp:include ...

  7. bootstrap在jsp中的应用

    http://www.bootcss.com/ 下载bootstrap的js,css文件: 在jsp中的应用: 第一步: 新建一个web项目 将bootstrap下载下来的文件放入WEB-INF下面的 ...

  8. jsp中超链接路径的写法

    主题 超链接不就是一个地址字符串吗?这能有什么花头? LZSB! 曾经我也是这么想的.... 最近对apache的学习让我对网页中超链接,CSS,js的路径的写法有了一些新的认识. 所以这篇文章主要分 ...

  9. jsp中头的导入两种方式区别

    1.<jsp:include page="top.jsp">先将top.jsp中的java脚本和jsp指令执行完毕以后再讲top.jsp页面加入面中 2.<%@ ...

随机推荐

  1. struts2值栈分析

    前段日子对ognl表达式不是很理解,看了几本书上关于ognl表达式的描述后还是感觉很难,前几天学习了struts2中值栈的内容,现在感觉ognl表达式其实很容易. struts2中利用值栈来存储数据, ...

  2. Linux多线程编程(不限Linux)

    前言 线程?为什么有了进程还需要线程呢,他们有什么区别?使用线程有什么优势呢?还有多线程编程的一些细节问题,如线程之间怎样同步.互斥,这些东西将在本文中介绍.我在某QQ群里见到这样一道面试题: 是否熟 ...

  3. 杭电2034——人见人爱A-B

    #include <stdio.h> #include <algorithm> using namespace std; int main () { int a[110],b[ ...

  4. IEEE 802.15.4协议学习之MAC层

        MAC负责建立于网络的同步,支持关联和取消关联.MAC层的安全以及控制物理信道访问机制.信道访问机制主要有以下几种:       1. 有序的物理无线信道访问机制     2. 协调器启动和维 ...

  5. ubuntu 常用参数设置

        在Linux下,对于参数的设置,一般来说,都遵循这个规律.每一个功能程序,一定对于一个对于名字的配置文件.     涉及到多用户的功能配置,一定有一个全局的配置文件,对所有用户都生效,而每个用 ...

  6. WindowsPhone8 数据库增删改查

    今天第一次在博客园发表文章,如果有的地方写的不对,还请大家指出! 1.这就是一个简单wp8数据库增删改查 1.创建数据表Person [Table] public class Person : INo ...

  7. C# http下载(支持断点续传)

    分享下项目里面自己封装的一个http下载类 功能如下: 1.支持断点续传 2.下载失败自动重试 3.超时等异常处理 using System; using System.Collections.Gen ...

  8. laravel步骤 (我是新手)

    1/需要一个wnmp之类的虚拟服务器 2/创建路由   php artisan make:route routes Route::group(['middleware' => ['web','a ...

  9. dedecms 分页样式

    <div class="dede_pages">  <ul class="pagelist">   {dede:pagelist lis ...

  10. Web Capacity Analysis Tool 压力测试工具使用笔记

    一.背景介绍 Web Capacity Analysis Tool是微软轻量级Web压力测试工具, 早先是IIS 6.0Resource Tool kit 工具包中的一个组件,现在独立出来有一个社区版 ...