简介
文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。
对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
文件上传
磁盘文件项工厂disk file item factory
1、文件上传页面和消息提示页面
核心API介绍
1.DiskFileItemFactory
作用:可以设置缓存大小以及临时文件保存位置.
默认缓存大小是 10240(10k).
临时文件默认存储在系统的临时文件目录下.(可以在环境变量中查看)
1.new DiskFileItemFactory();
缓存大小与临时文件存储位置使用默认的.
2.DiskFileItemFactory(int sizeThreshold, File repository)
sizeThreshold :缓存大小
repository:临时文件存储位置
注意,对于无参数构造,也可以设置缓存大小以及临时文件存储位置.
setSizeThreshold(int sizeThreshold)
setRepository(File repository)
2.ServletFileUpload
1.ServletFileUpload upload=new ServletFileUpload(factory);
创建一个上传工具,指定使用缓存区与临时文件存储位置.
2.List<FileItem> items=upload.parseRequest(request);
它是用于解析request对象,得到所有上传项.每一个FileItem就相当于一个上传项.
3.boolean flag=upload.isMultipartContent(request);
用于判断是否是上传.
可以简单理解,就是判断encType="multipart/form-data";
4.设置上传文件大小
void setFileSizeMax(long fileSizeMax) 设置单个文件上传大小
void setSizeMax(long sizeMax) 设置总文件上传大小
5.解决上传文件中文名称乱码
setHeaderEncoding("utf-8");
注意:如果使用reqeust.setCharacterEncoding("utf-8")也可以,但不建议使用。
ServletFileUpload的讲解.
1.ServletFileUpload upload=new ServletFileUpload(factory);
创建一个上传工具,指定使用缓存区与临时文件存储位置.
2.List<FileItem> items=upload.parseRequest(request);
它是用于解析request对象,得到所有上传项.每一个FileItem就相当于一个上传项.
3.boolean flag=upload.isMultipartContent(request);
用于判断是否是上传.
可以简单理解,就是判断encType="multipart/form-data";
4.设置上传文件大小.
void setFileSizeMax(long fileSizeMax) 设置单个文件上传大小 .
void setSizeMax(long sizeMax) 设置总文件上传大小 .
5.解决上传文件中文名称乱码.
setHeaderEncoding("utf-8");
注意:如果使用reqeust.setCharacterEncoding("utf-8")也可以,但不建议使用。
FileItem类:
1.isFormField
用于判断是否是上传组件.
如果是<input type="file">返回的就是false,否则返回true.
2.getFieldName();
返回值String,得到组件名称 <input name="">
3.getName();
返回值是String,得到的是上传文件的名称.
注意:浏览器不同,它们得到的效果不一样。
1.包含全路径名称 例如: C:\Users\Administrator\Desktop\a.txt
2.只包含上传文件名称 例如:a.txt
4.getString();
这个方法可以获取非上传组件的内容,相当于 getParameter方法作用。
问题:如果信息是中文,会出现乱码,解决方案 getString("utf-8");
如果是上传组件,上传的文件是文本文件,可以获取到文件文件的内容。
但是如果不是文件文件,例如:是一张图片,这样获取合适吗?
5.获取上传文件的内容,保存到服务器端.
item.getInputStream();它是用于读取上传文件内容的输入流.
使用文件复制操作就可以完成文件上传。
6.删除临时文件
item.delete();
总结:关于文件上传时的乱码问题:
1.上传文件名称乱码
ServletFileUpload.setHeaderEncoding("utf-8");
2.非上传组件内容乱码
FileItem.getString("utf-8");
3.思考:上传文件信息是否会乱码,需要解决吗?
不需要解决,因为我们在上传时,使用的字节流来进行复制。
问题
文件上传兼容浏览器问题
int idx=filename.lastIndexOf("\\");
if(inx!=-1){
//老版本浏览器
filename=filename.substring(idx+1);
}
UUID避免重复文件名
同一目录下文件过多
目录分离算法来进行文件分类:
唯一文件名取得hashcode&0xf来作为一级目录
右移4位&0xf作为二级目录,以此类推
upload.jsp页面的代码如下:
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/servlet/uploadHandleServlet2" enctype="multipart/form-data" method="post" 上传用户:<input type="text"name="username"><br/>
上传文件1:<input type="file" name="file1"><br/>
上传文件2:<input type="file" name="file2"><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
在文件上传的页面要用enctype=“multipart/form-data” method="post"来表示进行文件上传。
2、处理文件上传的Servlet
public class UploadHandleServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
File file = new File(savePath);
if(!file.exists()&&!file.isDirectory()){
System.out.println("目录或文件不存在!");
file.mkdir();
}
//消息提示
String message = "";
try {
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
//解决上传文件名的中文乱码
fileUpload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!fileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = fileUpload.parseRequest(request);
for (FileItem item : list) {
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
String name = item.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
String value1 = new String(name.getBytes("iso8859-1"),"UTF-8");
System.out.println(name+" "+value);
System.out.println(name+" "+value1);
}else{
//如果fileitem中封装的是上传文件,得到上传的文件名称,
String fileName = item.getName();
System.out.println(fileName);
if(fileName==null||fileName.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
//获取item中的上传文件的输入流
InputStream is = item.getInputStream();
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream(savePath+File.separator+fileName);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int length = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((length = is.read(buffer))>0){
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
fos.write(buffer, 0, length);
}
//关闭输入流
is.close();
//关闭输出流
fos.close();
//删除处理文件上传时生成的临时文件
item.delete();
message = "文件上传成功";
}
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message = "文件上传失败";
}
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3、文件上传的细节
上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的:
(1)、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
(2)、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
(3)、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
(4)、要限制上传文件的最大值。
(5)、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
4、改进后的servlet
public class UploadHandleServlet1 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//上传时生成的临时文件保存目录
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File file = new File(tempPath);
if(!file.exists()&&!file.isDirectory()){
System.out.println("目录或文件不存在!");
file.mkdir();
}
//消息提示
String message = "";
try {
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
diskFileItemFactory.setSizeThreshold(1024*100);
//设置上传时生成的临时文件的保存目录
diskFileItemFactory.setRepository(file);
//2、创建一个文件上传解析器
ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
//解决上传文件名的中文乱码
fileUpload.setHeaderEncoding("UTF-8");
//监听文件上传进度
fileUpload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
}
});
//3、判断提交上来的数据是否是上传表单的数据
if(!fileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
fileUpload.setFileSizeMax(1024*1024);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
fileUpload.setSizeMax(1024*1024*10);
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = fileUpload.parseRequest(request);
for (FileItem item : list) {
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
String name = item.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
String value1 = new String(name.getBytes("iso8859-1"),"UTF-8");
System.out.println(name+" "+value);
System.out.println(name+" "+value1);
}else{
//如果fileitem中封装的是上传文件,得到上传的文件名称,
String fileName = item.getName();
System.out.println(fileName);
if(fileName==null||fileName.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
//得到上传文件的扩展名
String fileExtName = fileName.substring(fileName.lastIndexOf(".")+1);
if("zip".equals(fileExtName)||"rar".equals(fileExtName)||"tar".equals(fileExtName)||"jar".equals(fileExtName)){
request.setAttribute("message", "上传文件的类型不符合!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
System.out.println("上传文件的扩展名为:"+fileExtName);
//获取item中的上传文件的输入流
InputStream is = item.getInputStream();
//得到文件保存的名称
fileName = mkFileName(fileName);
//得到文件保存的路径
String savePathStr = mkFilePath(savePath, fileName);
System.out.println("保存路径为:"+savePathStr);
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream(savePathStr+File.separator+fileName);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int length = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((length = is.read(buffer))>0){
//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
fos.write(buffer, 0, length);
}
//关闭输入流
is.close();
//关闭输出流
fos.close();
//删除处理文件上传时生成的临时文件
item.delete();
message = "文件上传成功";
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "单个文件超出最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}catch (FileUploadBase.SizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message = "文件上传失败";
}
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
public String mkFileName(String fileName){
return UUID.randomUUID().toString()+"_"+fileName;
}
public String mkFilePath(String savePath,String fileName){
//得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
int hashcode = fileName.hashCode();
int dir1 = hashcode&0xf;
int dir2 = (hashcode&0xf0)>>4;
//构造新的保存目录
String dir = savePath + "\\" + dir1 + "\\" + dir2;
//File既可以代表文件也可以代表目录
File file = new File(dir);
if(!file.exists()){
file.mkdirs();
}
return dir;
}
}
5、如果在文件上传中IO流成为了系统的性能瓶颈,可以考虑使用NIO来提高性能。改进servlet代码如下:
public class UploadHandleServlet2 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//上传时生成的临时文件保存目录
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File file = new File(tempPath);
if(!file.exists()&&!file.isDirectory()){
System.out.println("目录或文件不存在!");
file.mkdir();
}
//消息提示
String message = "";
try {
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
diskFileItemFactory.setSizeThreshold(1024*100);
//设置上传时生成的临时文件的保存目录
diskFileItemFactory.setRepository(file);
//2、创建一个文件上传解析器
ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
//解决上传文件名的中文乱码
fileUpload.setHeaderEncoding("UTF-8");
//监听文件上传进度
fileUpload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
}
});
//3、判断提交上来的数据是否是上传表单的数据
if(!fileUpload.isMultipartContent(request)){
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
fileUpload.setFileSizeMax(1024*1024);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
fileUpload.setSizeMax(1024*1024*10);
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = fileUpload.parseRequest(request);
for (FileItem item : list) {
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
String name = item.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
String value1 = new String(name.getBytes("iso8859-1"),"UTF-8");
System.out.println(name+" "+value);
System.out.println(name+" "+value1);
}else{
//如果fileitem中封装的是上传文件,得到上传的文件名称,
String fileName = item.getName();
System.out.println(fileName);
if(fileName==null||fileName.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
//得到上传文件的扩展名
String fileExtName = fileName.substring(fileName.lastIndexOf(".")+1);
if("zip".equals(fileExtName)||"rar".equals(fileExtName)||"tar".equals(fileExtName)||"jar".equals(fileExtName)){
request.setAttribute("message", "上传文件的类型不符合!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
System.out.println("上传文件的扩展名为:"+fileExtName);
//获取item中的上传文件的输入流
InputStream fis = item.getInputStream();
//得到文件保存的名称
fileName = mkFileName(fileName);
//得到文件保存的路径
String savePathStr = mkFilePath(savePath, fileName);
System.out.println("保存路径为:"+savePathStr);
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream(savePathStr+File.separator+fileName);
//获取读通道
FileChannel readChannel = ((FileInputStream)fis).getChannel();
//获取读通道
FileChannel writeChannel = fos.getChannel();
//创建一个缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
//判断输入流中的数据是否已经读完的标识
int length = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while(true){
buffer.clear();
int len = readChannel.read(buffer);//读入数据
if(len < 0){
break;//读取完毕
}
buffer.flip();
writeChannel.write(buffer);//写入数据
}
//关闭输入流
fis.close();
//关闭输出流
fos.close();
//删除处理文件上传时生成的临时文件
item.delete();
message = "文件上传成功";
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "单个文件超出最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}catch (FileUploadBase.SizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
message = "文件上传失败";
}
request.setAttribute("message",message);
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
public String mkFileName(String fileName){
return UUID.randomUUID().toString()+"_"+fileName;
}
public String mkFilePath(String savePath,String fileName){
//得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
int hashcode = fileName.hashCode();
int dir1 = hashcode&0xf;
int dir2 = (hashcode&0xf0)>>4;
//构造新的保存目录
String dir = savePath + "\\" + dir1 + "\\" + dir2;
//File既可以代表文件也可以代表目录
File file = new File(dir);
if(!file.exists()){
file.mkdirs();
}
return dir;
}
}
文件下载
超链接的方式
<td align="center"">
<a href="<c:url value="/bbsfile?filename=20150417.XLS&saveasfilename=template.xls"/>">下载导入模板</a>
</td>
浏览器支持可以打开,浏览器不支持就会提示下载
1、文件下载就是向客户端响应字节数据!
以前我们响应的都是html的字符数据,直接展示在浏览器上,现在要作为一个文件下载下来,而不是直接展示在浏览器上,
把一个文件变成字节数组,使用response.getOutputStream()来响应给浏览器!!!
2、下载的要求:两个头一个流!
Content-Type:你传递给客户端的文件是什么MIME类型,例如:image/pjpeg
* 通过文件名称调用ServletContext的getMimeType()方法,得到MIME类型!
Content-Disposition:它的默认值为inline,表示在浏览器窗口中打开!attachment;filename=xxx
* 在filename=后面跟随的是显示在下载框中的文件名称!
流:要下载的文件数据!
* 自己new一个输入流即可!
3、编写文件下载代码
描述:被下载的资源必须放到 WEB-INF 安全目录下(只要用户不能通过浏览器直接访问就OK),然后通过Servlet完成下载。在jsp页面中给出超链接,链接到DownloadServlet,并提供要下载的文件名称。然后DownloadServlet获取文件的真实路径,然后把文件写入到response.getOutputStream()流中。
download.jsp
<body>
This is my JSP page. <br>
<a href="<c:url value='/DownloadServlet?filename=a.avi'/>">a.avi</a><br/>
<a href="<c:url value='/DownloadServlet?filename=a.jpg'/>">a.jpg</a><br/>
<a href="<c:url value='/DownloadServlet?filename=a.txt'/>">a.txt</a><br/>
</body>
DownloadServlet.java (使用了commons-io-1.4.jar工具包)
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
/*
* 两个头一个流
* 1. Content-Type
* 2. Content-Disposition
* 3. 流:下载文件的数据
*/
//得到前台传过来的文件名
String filename = request.getParameter("filename");
//该文件的在服务器的路径
String filepath = this.getServletContext().getRealPath("/WEB-INF/uploads/" + filename);
File file = new File(filepath);
if(!file.exists()) {
response.getWriter().print("您要下载的文件不存在!");
return;
}else{
//设置2个响应头
//通过文件名称获取MIME类型(根据文件名的后缀)
response.setHeader("Content-Type", this.getServletContext().getMimeType(filename));
//该头信息,可以使下载框显示下载的文件名
response.setHeader("Content-Disposition", "attachment;filename=" + filenameEncoding("流光%飞舞.mp3", request));
// 1个流
FileInputStream input = new FileInputStream(file);
ServletOutputStream output = response.getOutputStream();// 获取绑定了响应端的流
IOUtils.copy(input, output);//把输入流中的数据写入到输出流中。
input.close();
}
}
// 解决不同浏览器中文乱码问题,用来对下载的文件名称进行编码的!
public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {
String agent = request.getHeader("User-Agent"); //获取浏览器
if (agent.contains("Firefox")) { //火狐用的是BASE64Encoder 来编码和解码
filename = "=?utf-8?B?" + new BASE64Encoder().encode(filename.getBytes("utf-8")) + "?=";
} else { //其他浏览器用的都是URLEncoder 来编码和解码
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
4、下载的细节
4.1设置响应头的目的:
Content-Type 文件的MIME类型
Content-Disposition 响应头属性有两种类型:inline 和 attachment.
inline :将文件内容直接显示在页面 (默认)。
attachment:弹出对话框让用户下载文件。添加content-disposition头,指定了在下载框中显示的文件名称。
如:response.setHeader("Content-Disposition", "attachment;filename=白冰.jpg" );