首页 > 编程语言 >Java Web实现文件下载的几种方式

Java Web实现文件下载的几种方式

时间:2023-11-24 17:44:33浏览次数:41  
标签:Web return String 几种 import Java response public 下载

文件下载可以说是网站的基础功能,要实现最下载功能,有一种最基本的方法,那就是将超链接的href属性指向对应的资源文件。

如下面连接指向了百度首页的图片:

​ ​I'm the index of Baidu​​

但这种方式的缺陷也是很明显的,目录信息被获取,不利于信息安全。其实信息安全还是其次,主要还是因为它不方便。如果直接指向资源文件,那么浏览器会自动打开图片等一些文件,而不会弹出窗口提示用户保存。

因此这种方式并不能很好地解决下载的问题。因此就有了下面的几种下载方式。

而在Java中,要实现下载功能一般有三种实现方式:

1、使用Servlet实现文件下载

2、在Struts中用Servlet实现下载

3、使用Struts框架提供的文件下载功能

其实这三种实现方式的原理都一样,都是利用InputStream从文件中读取数据,然后利用OutputStream将数据接入到返回客户端的response中。

其核心代码如下:

1 try {
2 InputStream inStream = new FileInputStream(file);
3 ServletOutputStream servletOS = response.getOutputStream();
4 byte[] buf = new byte[4096];
5 int readLength;
6 while((readLength = inStream.read(buf))!= -1)
7 {
8 servletOS.write(buf, 0, readLength);
9 }
10 inStream.close();
11 servletOS.flush();
12 servletOS.close();
13 }
14 catch(Exception e)
15 {
16 e.printStackTrace();
17 }
18 return response;

其中第一种在Servlet中实现文件下载是最原始的下载方式。而第二种在Struts中用Servlet实现文件下载也是最原始的方式,只不过我们是在Struts的Action中进行操作,不用去创建Servlet。

而第三种则是Struts对文件下载功能进行了封装,我们只要按照其规定的配置就可以直接使用。

这几种方式各有各的优缺点,选择适合自己的方式即可。下面对上面提到的三种方式进行详细解析:

一、使用Servlet实现文件下载

这种方式性能最好,条理最清晰,但是可能代码量多了点。

准备:只需Java的JDK即可运行。

1、在web.xml中进行Servlet配置

1 <?xml version="1.0" encoding="UTF-8"?>
2 <web-app version="2.5"
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
7
8 <!-- 文件下载 -->
9 <servlet>
10 <servlet-name>fileDownLoadServlet</servlet-name>
11 <servlet-class>com.chanshuyi.download.FileDownLoadServlet</servlet-class>
12 </servlet>
13 <servlet-mapping>
14 <servlet-name>fileDownLoadServlet</servlet-name>
15 <url-pattern>/fileDownLoadServlet</url-pattern>
16 </servlet-mapping>
17 </web-app>

2、创建Servlet类

1 package com.chanshuyi.download;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.UnsupportedEncodingException;
8 import java.net.URLEncoder;
9
10 import javax.servlet.ServletException;
11 import javax.servlet.ServletOutputStream;
12 import javax.servlet.http.HttpServlet;
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpServletResponse;
15
16 /**
17 * 文件下载Servlet
18 * @param filePath 下载文件相对于项目根目录的相对地址</P>如:uploaded\hello.txt
19 * @author chenyr
20 *
21 */
22 @SuppressWarnings("serial")
23 public class FileDownLoadServlet extends HttpServlet {
24
25 /** 项目的根目录</P>如:D:\Workspaces\DownUpProject\WebRoot\ **/
26 private String rootPath;
27
28 /** 下载文件的相对于项目根目录的相对路径 **/
29 private String filePath;
30
31 /** 下载文件在磁盘的绝对路径 **/
32 private String fullPath;
33
34 /** 下载文件名 **/
35 private String fileName;
36
37 /** 编码过后的下载文件名 **/
38 private String encodeFileName;
39
40 /**
41 * 自定义init,用于初始化下载所属属性
42 * @param request
43 * @return
44 * @throws UnsupportedEncodingException
45 */
46 public boolean myInit(HttpServletRequest request)
47 {
48 boolean flag = false;
49 try
50 {
51 setRootPath(this.getServletContext().getRealPath("/"));
52 setFilePath(new String(request.getParameter("filePath").getBytes("iso-8859-1"), "utf-8"));
53 setFullPath(getRootPath() + getFilePath());
54
55 setFileName(getFilePath().substring(getFilePath().lastIndexOf("\\") + 1));
56 setEncodeFileName(URLEncoder.encode(getFileName(), "utf-8")); //支持中文文件名
57
58 flag = true;
59 }
60 catch(Exception e)
61 {
62 e.printStackTrace();
63 }
64 return flag;
65 }
66
67 /**
68 * Servlet类的服务方法
69 */
70 @Override
71 protected void service(HttpServletRequest request,
72 HttpServletResponse response) throws ServletException, IOException {
73 download(request, response);
74 }
75
76 /**
77 * 文件下载
78 * @param path
79 * @param request
80 * @param response
81 * @return
82 * @throws UnsupportedEncodingException
83 */
84 public HttpServletResponse download(HttpServletRequest request, HttpServletResponse response){
85 /* 初始化相关属性信息 */
86 myInit(request);
87
88 /* 检查文件是否存在 */
89 File file = new File(getFullPath());
90 if(!file.exists())
91 {
92 System.out.println("文件不存在:" + file.getAbsolutePath());
93 return null;
94 }
95
96 /* 设置response头信息 */
97 response.reset();
98 response.setContentType("application/octet-stream"); //代表任意二进制数据
99 response.addHeader("Content-Disposition", "attachment;filename=\"" + getEncodeFileName() + "\"");
100 response.setContentLength((int)file.length());
101
102 /* 读取文件数据流 */
103 if(file.exists())
104 {
105 /* 读取文件数据 */
106 if((int)file.length() != 0)
107 {
108 try
109 {
110 InputStream inStream = new FileInputStream(file);
111
112 ServletOutputStream servletOS = response.getOutputStream();
113 byte[] buf = new byte[4096];
114 int readLength;
115 while((readLength = inStream.read(buf))!= -1)
116 {
117 servletOS.write(buf, 0, readLength);
118 }
119
120 inStream.close();
121 servletOS.flush();
122 servletOS.close();
123 }
124 catch(Exception e)
125 {
126 e.printStackTrace();
127 }
128 }
129 }
130 return response;
131 }
132
133 /*
134 * GET/SET
135 */
136 public String getFilePath() {
137 return filePath;
138 }
139
140 public void setFilePath(String filePath) {
141 this.filePath = filePath;
142 }
143
144 public String getFullPath() {
145 return fullPath;
146 }
147
148 public void setFullPath(String fullPath) {
149 this.fullPath = fullPath;
150 }
151
152 public String getFileName() {
153 return fileName;
154 }
155
156 public void setFileName(String fileName) {
157 this.fileName = fileName;
158 }
159
160 public String getEncodeFileName() {
161 return encodeFileName;
162 }
163
164 public void setEncodeFileName(String encodeFileName) {
165 this.encodeFileName = encodeFileName;
166 }
167
168 public String getRootPath() {
169 return rootPath;
170 }
171
172 public void setRootPath(String rootPath) {
173 this.rootPath = rootPath;
174 }
175 }

这个Servlet类对下载功能进行很好的封装,只需要传入名字为:filePath的参数就可以进行下载(filePath是下载文件相对于根目录[WEBROOT目录]的相对路径)。

98行设置response的contentType为application/octet-stream,可以实现任意类型文件的下载。

56行设置URLEncoder.encode对文件名进行编码转换,实现对中文文件名的下载支持。

3、创建访问页面测试

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%
3 String path = request.getContextPath();
4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
5 %>
6
7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
8 <html>
9 <head>
10 <base href="<%=basePath%>">
11
12 <title>My JSP 'index.jsp' starting page</title>
13 <meta http-equiv="pragma" content="no-cache">
14 <meta http-equiv="cache-control" content="no-cache">
15 <meta http-equiv="expires" content="0">
16 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17 <meta http-equiv="description" content="This is my page">
18 <!--
19 <link rel="stylesheet" type="text/css" href="styles.css">
20 -->
21 </head>
22
23 <body>
24 <a href="fileDownLoadServlet?filePath=uploaded\通讯录.xls">哈哈,测试文件下载</a>
25 </body>
26 </html>

二、在Struts中用Servlet实现下载

这种方式其实就是将数据流写入response中,其实现方式与第一种完全相同。不同的是在Servlet类中,我们可以直接得到request、response、ServletContext,但是在Struts的Action中我们必须通过其他方式得到这几个变量。

下面的代码实在第一种实现方式的代码的基础上进行少量修改而成的,它实现了在Struts Action中下载的功能:

package com.chanshuyi.download;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class FileDownloadViaServlet extends ActionSupport {

HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext servletContext = ServletActionContext.getServletContext();

/** 项目的根目录</P>如:D:\Workspaces\DownUpProject\WebRoot\ **/
private String rootPath;

/** 下载文件的相对于项目根目录的相对路径 **/
private String filePath;

/** 下载文件在磁盘的绝对路径 **/
private String fullPath;

/** 下载文件名 **/
private String fileName;

/** 编码过后的下载文件名 **/
private String encodeFileName;

/**
* 自定义init,用于初始化下载所属属性
* @param request
* @return
* @throws UnsupportedEncodingException
*/
public boolean myInit()
{
boolean flag = false;

try
{
setRootPath(servletContext.getRealPath("/"));
setFilePath(new String(request.getParameter("filePath").getBytes("iso-8859-1"), "utf-8"));
setFullPath(getRootPath() + getFilePath());

setFileName(getFilePath().substring(getFilePath().lastIndexOf("\\") + 1));
setEncodeFileName(URLEncoder.encode(getFileName(), "utf-8")); //支持中文文件名

flag = true;
}
catch(Exception e)
{
e.printStackTrace();
}
return flag;
}

/**
* Action执行方法
*/
@Override
public String execute() {
download();
return null;
}

/**
* 文件下载
* @param path
* @param request
* @param response
* @return
* @throws UnsupportedEncodingException
*/
public HttpServletResponse download(){
/* 初始化相关属性信息 */
myInit();

/* 检查文件是否存在 */
File file = new File(getFullPath());
if(!file.exists())
{
System.out.println("文件不存在:" + file.getAbsolutePath());
return null;
}

/* 设置response头信息 */
response.reset();
response.setContentType("application/octet-stream"); //代表任意二进制数据
response.addHeader("Content-Disposition", "attachment;filename=\"" + getEncodeFileName() + "\"");
response.setContentLength((int)file.length());

/* 读取文件数据流 */
if(file.exists())
{
/* 读取文件数据 */
if((int)file.length() != 0)
{
try
{
InputStream inStream = new FileInputStream(file);

ServletOutputStream servletOS = response.getOutputStream();
byte[] buf = new byte[4096];
int readLength;
while((readLength = inStream.read(buf))!= -1)
{
servletOS.write(buf, 0, readLength);
}

inStream.close();
servletOS.flush();
servletOS.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
return response;
}

/*
* GET/SET
*/
public String getFilePath() {
return filePath;
}

public void setFilePath(String filePath) {
this.filePath = filePath;
}

public String getFullPath() {
return fullPath;
}

public void setFullPath(String fullPath) {
this.fullPath = fullPath;
}

public String getFileName() {
return fileName;
}

public void setFileName(String fileName) {
this.fileName = fileName;
}

public String getEncodeFileName() {
return encodeFileName;
}

public void setEncodeFileName(String encodeFileName) {
this.encodeFileName = encodeFileName;
}

public String getRootPath() {
return rootPath;
}

public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}

}

三、使用Struts框架提供的文件下载功能

通过Struts封装的方式实现文件下载,我们需要在Struts配置文件中进行Response HTTP头等信息的设置,以及建立对应的Action。

准备:导入Struts所需的Jar包,并搭建好Struts环境。不清楚的,可以点这里:​​Struts框架配置详解​​

1、在Struts中添加Action

1 <!-- 文件下载 -->
2 <action name="fileDownload" class="com.chanshuyi.download.FileDownLoadAction" method="download">
3 <!-- 初始文件名 -->
4 <param name="fileName">佛山“狠刹”四风网络监督平台短信责任人填报表V1.0.xls</param>
5 <result name="success" type="stream">
6 <param name="contentType">application/vnd.ms-excel</param>
7 <param name="inputName">mbInputStream</param>
8 <param name="contentDisposition">attachment;filename=${downloadFileName}</param>
9 <param name="bufferSize">4096</param>
10 </result>
11 </action>

其中<param name="inputName">mbInputStream</param>中的mbInputStream对应Action中类型为InputStream的属性。

2、创建Action类

1 package com.chanshuyi.download;
2
3 import java.io.FileNotFoundException;
4 import java.io.InputStream;
5 import java.io.UnsupportedEncodingException;
6 import java.net.URLEncoder;
7
8 import javax.servlet.http.HttpServletRequest;
9
10 import org.apache.struts2.ServletActionContext;
11
12 import com.opensymphony.xwork2.ActionSupport;
13
14 public class FileDownLoadAction extends ActionSupport {
15
16 /** 项目的根目录</P>如:D:\Workspaces\DownUpProject\WebRoot\ **/
17 private String rootPath;
18
19 /** 下载文件的相对于项目根目录的相对路径 **/
20 private String filePath;
21
22 /** 下载文件在磁盘的绝对路径 **/
23 private String fullPath;
24
25 /** 下载文件名 **/
26 private String fileName;
27
28 /** 编码过后的下载文件名 **/
29 private String encodeFileName;
30
31
32 /** 对应于配置文件的输入流 **/
33 private InputStream inputStream;
34
35 public String getRootPath() {
36 return rootPath;
37 }
38
39 public void setRootPath(String rootPath) {
40 this.rootPath = rootPath;
41 }
42
43 public String getFilePath() {
44 return filePath;
45 }
46
47 public void setFilePath(String filePath) {
48 this.filePath = filePath;
49 }
50
51 public String getFullPath() {
52 return fullPath;
53 }
54
55 public void setFullPath(String fullPath) {
56 this.fullPath = fullPath;
57 }
58
59 public String getFileName() {
60 return fileName;
61 }
62
63 public void setFileName(String fileName) {
64 this.fileName = fileName;
65 }
66
67 public void setEncodeFileName(String encodeFileName) {
68 this.encodeFileName = encodeFileName;
69 }
70
71 /**
72 * 初始化参数
73 * @throws UnsupportedEncodingException
74 */
75 public void myInit() throws UnsupportedEncodingException
76 {
77 HttpServletRequest request = ServletActionContext.getRequest();
78
79 setRootPath(ServletActionContext.getServletContext().getRealPath("/"));
80 setFilePath(new String(request.getParameter("filePath").getBytes("iso-8859-1"), "utf-8"));
81 setFullPath(getRootPath() + getFilePath());
82
83 setFileName(getFilePath().substring(getFilePath().lastIndexOf("\\") + 1));
84 setEncodeFileName(URLEncoder.encode(getFileName(), "utf-8")); //支持中文文件名
85 }
86
87 /**
88 * 对应的Action方法
89 * @return
90 * @throws UnsupportedEncodingException
91 */
92 public String download() throws UnsupportedEncodingException
93 {
94 myInit();
95 return SUCCESS;
96 }
97
98 /**
99 * 对文件名进行编码转换,以支持中文文件名
100 * @return
101 */
102 public String getEncodeFileName() {
103 return encodeFileName;
104 }
105
106 /**
107 * 获取下载文件的输入流
108 * @return
109 * @throws FileNotFoundException
110 */
111 public InputStream getInputStream() throws FileNotFoundException {
112 return new java.io.FileInputStream(getFullPath());
113 }
114 }

参考文章:http://blog.ncmem.com/wordpress/2023/11/24/java-web%e5%ae%9e%e7%8e%b0%e6%96%87%e4%bb%b6%e4%b8%8b%e8%bd%bd%e7%9a%84%e5%87%a0%e7%a7%8d%e6%96%b9%e5%bc%8f/

欢迎入群一起讨论

 

 

标签:Web,return,String,几种,import,Java,response,public,下载
From: https://www.cnblogs.com/songsu/p/17854336.html

相关文章

  • JAVA进阶 —— 方法引用
    原文链接:https://blog.csdn.net/hdakj22/article/details/129453599一、内容概述方法引用可以拆分为方法和引用两方面:方法引用:把已经有的方法拿过来用,当作函数接口中抽象方法的方法体。::(方法引用符)但是要注意:并不是所有的方法都可以直接引用,需要满足以下四种条件引用......
  • JavaScript数组中的常用函数解析
    1.splice方法当使用splice()方法时,可以传递不同的参数来实现不同的操作。以下是splice()方法的参数说明:array.splice(start,deleteCount,item1,item2,...);start:必需,指定要进行操作的起始索引位置。如果该值为负数,则表示从数组末尾开始计算的偏移量。例如,-1表示倒数第......
  • Prometheus+Alertmanager + Webhook-dingtalk
    一、下载alertmanager和webhook-dingtalkwww.github.com搜索alertmanagerwebhook-dingtalk1、解压、安装webhook-dingtalktar-zxvfprometheus-webhook-dingtalk-2.1.0.linux-amd64.tar.gzmvprometheus-webhook-dingtalk-2.1.0.linux-amd64/usr/local/webhook......
  • java 关于 Finalizer 过多导致内存(Res)缓慢上涨
     病因:事情的起因是由Flume的项目采集问题引发的.测试人员发现用top命令查看采集进程的Res一直不断上涨姿势.所以怀疑是内存泄漏.  一,对症下药首先,第一步肯定是先瞅瞅代码,看看有没有那些资源啥的没关闭,正如读者所想----没有发现.二,通过辅助工具最......
  • 这篇保证你彻底搞懂Java NIO的Selector事件选择器
     Selector提供选择执行已经就绪的任务的能力,使得多元I/O成为可能,就绪选择和多元执行使得单线程能够有效率地同时管理多个I/Ochannel。C/C++许多年前就已经有select()和poll()这两个POSIX(可移植性操作系统接口)系统调用可供使用。许多os也提供相似的功能,但对Java程序......
  • Java实验报告五
    实验五实验名称:文件与I/O流实验目的:掌握文件与输入输出流的使用。实验时间:(2学时)实验类型:验证型实验内容:1.创建类:FindFile.java,遍历当前目录,打印目录中文件名称,目录打印”isDirectory”,文件打印“isfile”。修改程序打印当前目录及子目录信息。提示:当前目录名用......
  • JavaWeb中的文件的上传和下载
    文件上传1.要有一个form标签,method=post请求2.form标签的encType属性的值必须为multipart/form-data值3.在from标签中使用inputtype=file添加上传的文件4.编写服务器代码接收上传的数据Content-Type:表示提交的数据类型enctype="multipart/form-data":表示提交的数据,以多段(每......
  • 区块链与Web3.0:创新与监管的交汇
    币安被罚43亿美元,赵长鹏认罪辞职,全球最大加密货币交易所币安及其创始人赵长鹏与美国政府达成了认罪协议,为违反美国反洗钱法律接受了高额罚金。这一事件引发了对加密货币领域监管的热议,也呈现出了监管与技术创新之间的挑战。在区块链和加密货币领域的创新中,我们看到了未来金融生态......
  • Java线程生命周期
    操作系统线程生命周期操作系统线程生命状态有5种。初始状态(New)进程正在被创建时的状态。仅为线程对象开辟了一块堆内存,实际上线程在操作系统层面还未创建。就绪状态(Ready)可运行,由于其他进程处于运行状态而暂时停止运行运行状态(Running)该进程此时正占用CPU......
  • Java实验报告
    实验一实验名称:JAVA中循环结构实验目的:熟悉循环结构,熟悉JAVA类的定义以及参数的传递。实验时间:(2学时)实验类型:验证型实验内容:(1)金字塔:Pyramid.java在屏幕上显示一个由星型符号“*”组成的金字塔图案,要求用户设置金字塔的高度,程序能根据用户设置的高度打印金字塔,......