Java进阶学习第二十二天——上传与下载
Posted 鹿天斐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java进阶学习第二十二天——上传与下载相关的知识,希望对你有一定的参考价值。
文档版本 | 开发工具 | 测试平台 | 工程名字 | 日期 | 作者 | 备注 |
---|---|---|---|---|---|---|
V1.0 | 2016.06.05 | lutianfei | none |
- Servlet规范中
- servlet有初始化参数
- Filter有初始化参数
- Listener没有初始化参数,要使用,在开发中一般使用
<context-param>
servletContext的初始化参数.
文件上传
问题:什么是文件上传?为什么使用文件上传?
- 就是将客户端资源,通过网络传递到服务器端。
- 就是因为数据比较大,我们必须通过文件上传才可以完成将数据保存到服务器端操作。
文件上传的本质:就是IO流的操作。
实现web开发中的文件上传功能,需完成如下二步操作:
- 在web页面中添加上传输入项
- 在servlet中读取上传文件的数据,并保存到服务器硬盘中
如何在web页面中添加上传输入项?
<input type=“file”>
标签用于在web页面中添加文件上传输入项,设置文件上传输入项时须注意:
- 1、必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据。
- 2、必须把form的enctype属值设为
multipart/form-data
。设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,并使用MIMIE协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。 - 3、表单的提交方式要是post
如何在Servlet中读取文件上传数据,并保存到本地硬盘中?
- Request对象提供了一个getInputStream方法,通过这个方法可以读取到客户端提交过来的数据。但由于用户可能会同时上传多个文件,在servlet端编程直接读取上传数据,并分别解析出相应的文件数据是一项非常麻烦的工作。
- 为方便用户处理文件上传数据,Apache 开源组织提供了一个用来处理表单文件上传的一个开源组件(
Commons-fileupload
),该组件性能优异,并且其API使用极其简单,可以让开发人员轻松实现web文件上传功能,因此在web开发中实现文件上传功能,通常使用Commons-fileupload
组件实现。
使用
Commons-fileupload组件
实现文件上传,需要导入该组件相应的支撑jar包:Commons-fileupload
和commons-io
。commons-io
不属于文件上传组件的开发jar文件,但Commons-fileupload
组件从1.1 版本开始,它工作时需要commons-io包
的支持。
文件上传步骤
1.导入jar包
commons-fileupload-1.2.1.jar
: 文件上传commons-io-1.4.jar
: 它是提供的io工具.- commons-fileupload 它有三个核心
- 1.DiskFileItemFactory类
- 2.ServletFileUpload类
- 3.FileItem
2.快速入门
- 1.创建upload2.jsp页面
<form action="${pageContext.request.contextPath}/upload2" method="post" encType="multipart/form-data">
<input type="file" name="f"><br>
<input type="submit" value="上传">
</form>
- 2.创建Upload2Servlet
- 1.创建一个 DiskFileItemFactory,设置缓冲区大小和临时文件目录
DiskFileItemFactory factory=new DiskFileItemFactory();
- 2.创建 ServletFileUpload类,设置上传文件的大小限制。
ServletFileUpload upload=new ServletFileUpload(factory);
- 3.解析所有上传数据,调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。
List<FileItem> items = upload.parseRequest(request);
- 1.创建一个 DiskFileItemFactory,设置缓冲区大小和临时文件目录
3.遍历items集合,集合中的每一项,就是一个上传数据
- 1.
isFormField
();
- True 为普通表单字段,则调用 getFieldName、getString 方法得到字段名和字段值
- False 为上传文件,则调用 getInputStream 方法得到* 数据输入流*,从而读取上传数据。
- 2.
getFieldName
();
- 返回值String,得到
组件名称
<input name="">
- 返回值String,得到
- 3.
getName
();
- 返回值是String,得到的是上传文件的名称.
- 注意:浏览器不同,它们得到的效果不一样。
- 1.包含全路径名称 例如:
C:\Users\Administrator\Desktop\a.txt
- 2.只包含上传文件名称 例如:
a.txt
- 1.包含全路径名称 例如:
- 4.getString();
- 这个方法可以获取非上传组件的内容,相当于getParameter方法作用。 如果是上传组件,上传的文件是文本文件,可以获取到文件文件的内容。但是如果不是文本文件,则无法正确传输。
- 5.获取上传文件的内容,保存到服务器端.
item.getInputStream();
它是用于读取上传文件内容的输入流。- 使用文件复制操作就可以完成文件上传。
IOUtils.copy(item.getInputStream(), fos);
- 1.
fileupload组件工作流程
FileUpload上传操作核心API
获取temp目录部署到tomcat后的绝对磁盘路径的技巧
File file = new File(this.getServletContext().getRealPath("/temp"));
1.
DiskFileItemFactory
磁盘文件项工厂类,是创建FileItem
对象的工厂:- 作用:可以设置缓存大小以及临时文件保存位置。
- 默认缓存大小是 10240(10k).
- 临时文件默认存储在系统的临时文件目录下.(可以在环境变量中查看)
- 1.new
DiskFileItemFactory
();
- 缓存大小与临时文件存储位置使用默认的
- 2.
DiskFileItemFactory
(int sizeThreshold, File repository)
- sizeThreshold :缓存大小
- repository:临时文件存储位置
- 注意,对于无参数构造,也可以设置缓存大小以及临时文件存储位置
- setSizeThreshold(int sizeThreshold)
- setRepository(File repository)
- 内存缓冲区: 上传文件时,上传文件的内容优先保存在内存缓冲区中,当上传文件大小超过缓冲区大小,就会在服务器端产生临时文件
- 临时文件存放位置: 保存超过了内存缓冲区大小上传文件而产生临时文件
- 产生临时文件可以通过 FileItem的
delete方法
删除
2.
ServletFileUpload
文件上传核心类 ,负责处理上传的文件数据,并将表单中每个输入项封装成一个 FileItem 对象中。常用方法有:- static boolean
isMultipartContent
(javax.servlet.http.HttpServletRequest request) 判断是否是上传,即判断request的编码方式是否为multipart/form-data - java.util.List
parseRequest
(javax.servlet.http.HttpServletRequest request) 解析request,将请求体每个部分封装 FileItem对象,返回List<FileItem>
- void
setFileSizeMax
(long fileSizeMax) 设置单个文件上传大小 - void
setSizeMax
(long sizeMax) 设置总文件上传大小 - void
setHeaderEncoding
(java.lang.String encoding) 设置编码集 解决上传文件名乱码 setProgressListener
(ProgressListener pListener)实时监听文件上传状态- ServletFileUpload(factory);创建一个上传工具,指定使用缓存区与临时文件存储位置.
- static boolean
3、
FileItem
表示文件上传表单中 每个数据部分,用来表示文件上传表单中的一个上传文件对象或者普通表单对象- boolean
isFormField
() 判断该数据项是否为文件上传项,true 不是文件上传 false 是文件上传
- 如果判断是一个普通表单对象
- String
getFieldName
() 获得普通表单对象的name属性<input name="">
- String
getString
(String encoding) 获得普通表单对象的value属性,可以用encoding进行编码设置
- String
- 如果判断是一个文件上传对象
- String
getName
() 获得上传文件的文件名(有些浏览器会携带客户端路径)
- 注意:浏览器不同,它们得到的效果不一样。
- 1.包含全路径名称 例如: C:\Users\Administrator\Desktop\a.txt
- 2.只包含上传文件名称 例如:a.txt
- 注意:浏览器不同,它们得到的效果不一样。
- InputStream
getInputStream
() 获得上传文件的输入流 delete
() 在关闭FileItem输入流后,删除临时文件
- String
- 如果判断是一个普通表单对象
- boolean
总结:关于文件上传时的乱码问题:
- 1.上传文件名称乱码
- ServletFileUpload.setHeaderEncoding(“utf-8”);
- 2.非上传组件内容乱码
- FileItem.getString(“utf-8”);
- 3.思考:上传文件信息是否会乱码,需要解决吗?
- 不需要解决,因为我们在上传时,使用的字节流来进行复制。
- 1.上传文件名称乱码
if(fileItem.isFormField()){
// 不是上传项
java.lang.String getFieldName() 获得普通表单项name属性
java.lang.String getString() / java.lang.String getString(java.lang.String encoding) 获得普通表单项value属性 传入编码集用来解决输入value乱码
}else{
// 是上传项
java.lang.String getName() 获得上传文件名 (注意IE6存在路径)
java.io.InputStream getInputStream() 获得上传文件内容输入流
// 上传文件
void delete() 删除临时文件(删除时,必须要管理输入输出流)
}
- 注意事项:因为文件上传表单采用编码方式
multipart/form-data
与传统url
编码不同,所有getParameter 方法不能使用 setCharacterEncoding 无法解决输入项乱码问题。
JavaScript的多文件上传表单
- 技巧:
- 每次动态增加一个文件上传输入框,都把它和删除按纽放置在一个单独的div中,并对删除按纽的onclick事件进行响应,使之删除删除按纽所在的div。
- 如:
this.parentNode.parentNode.removeChild(this.parentNode);
多文件上传
<script type="text/javascript">
function addFile(){
var div=document.getElementById("content");
div.innerhtml+="<div><input type=‘file‘ name=‘f‘><input type=‘button‘ value=‘remove file‘ onclick=‘removeFile(this)‘></div>";
}
function removeFile(btn){
document.getElementById("content").removeChild(btn.parentNode);
}
</script>
<body>
<input type="button" value="add File" onclick="addFile();">
<br>
<br>
<form action="${pageContext.request.contextPath}/upload4" method="post" encType="multipart/form-data">
<input type="file" name="f"><br>
<div id="content">
</div>
<input type="submit" value="上传">
</form>
</body>
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// 1.创建 DiskFileItemFactory
File file = new File(this.getServletContext().getRealPath("/temp"));// 获取temp目录部署到tomcat后的绝对磁盘路径
DiskFileItemFactory factory = new DiskFileItemFactory(1024 * 100, file); // 使用默认的.
// 2.创建ServletFileUpload
ServletFileUpload upload = new ServletFileUpload(factory);
boolean flag = upload.isMultipartContent(request); // 用于判断是否是上传操作.
if (flag) {
// 解决上传文件名称中文乱码
upload.setHeaderEncoding("utf-8");
// 设置上传文件大小
// upload.setSizeMax(1024 * 1024 * 10);// 总大小为10m
try {
List<FileItem> items = upload.parseRequest(request);// 解决request,得到所有的上传项FileItem
// 3.得到所有上传项
for (FileItem item : items) {
if (!item.isFormField()) {
// 上传组件
String name = item.getName(); // 上传文件名称
// 得到上传文件真实名称
String filename = FileUploadUtils.getRealName(name);
// 得到随机名称
String uuidname = FileUploadUtils
.getUUIDFileName(filename);
// 得到随机目录
String randomDirectory = FileUploadUtils
.getRandomDirectory(filename);
// 注意:随机目录可能不存在,需要创建.
String parentPath = this.getServletContext()
.getRealPath("/upload");
File rd = new File(parentPath, randomDirectory);
if (!rd.exists()) {
rd.mkdirs();
}
IOUtils.copy(item.getInputStream(),
new FileOutputStream(new File(rd, uuidname)));
// 删除临时文件
item.delete();
}
}
} catch (FileUploadException e) {
// e.printStackTrace();
response.getWriter().write(e.getMessage());
return;
}
} else {
response.getWriter().write("不是上传操作");
return;
}
}
上传文件存在的问题
上传文件在服务器端保存位置问题
1.保存在可以被浏览器直接访问的位置
- 例如:商城的商品图片
- 保存在工程的WebRoot下的路径(不包含META-INF以及WEB-INF目录及其子目录)
2.保存在不能被浏览器直接访问的位置
- 例如:付费的视频。
- 1.工程中
META-INF
、WEB-INF
目录及其子目录 - 2.不受tomcat服务器管理目录 例如: WebRoot/WEB-INF/upload 、c:\ 、d:\abc
上传文件在同一个目录重名问题
如果文件重名,后上传文件就会覆盖先上传文件,在开发中解决这个问题,可以给上传文件起随机名称。
文件名 UUID
filename = UUID.randomUUID().toString() + "_" + filename;
为了防止同一个目录下方上传文件数量过多 —- 必须采用目录分离算法
- 1) 按照上传时间进行目录分离 (周、月 )
- 2) 按照上传用户进行目录分离 —– 为每个用户建立单独目录
- 3) 按照固定数量进行目录分离 —— 假设每个目录只能存放3000个文件 ,每当一个目录存满3000个文件后,创建一个新的目录
- 4) 按照唯一文件名的hashcode 进行目录分离
public static String generateRandomDir(String uuidFileName) {
// 获得唯一文件名的hashcode
int hashcode = uuidFileName.hashCode();
// 获得一级目录
int d1 = hashcode & 0xf;
// 获得二级目录
int d2 = (hashcode >>> 4) & 0xf;
return "/" + d2 + "/" + d1;// 共有256目录l
}
乱码问题
- 普通编写项 value属性乱码: fileItem.getString(编码集);
- 上传文件项 文件名乱码 : fileupload.setHeaderEncoding(编码集);
文件下载
- 文件下载的方式:
- 1.超连接下载
- 2.服务器端通过流下载(服务器端编程)
超链接直接指向下载资源
- 如果文件格式浏览器识别,将直接打开文件,显示在浏览器上, 如果文件格式浏览器不识别,将弹出下载窗口
对于浏览器识别格式的文件,通过另存为进行下载
客户端访问服务器静态资源文件时,静态资源文件是通过 缺省Servlet返回的,在tomcat配置文件
conf/web.xml
找到org.apache.catalina.servlets.DefaultServlet
eg:超连接下载
download1.jsp
<a href=‘${pageContext.request.contextPath}/upload/a.bmp‘>a.bmp</a><br>
<a href=‘${pageContext.request.contextPath}/upload/a.doc‘>a.doc</a><br>
<a href=‘${pageContext.request.contextPath}/upload/a.txt‘>a.txt</a><br>
<a href=‘${pageContext.request.contextPath}/upload/tk.mp3‘>tk.mp3</a><br>
在服务器端编程完成下载
- 编写服务器程序,读取服务器端文件,完成下载 必须设置两个头信息 ,来自
MIME
协议
- Content-Type
- Content-Disposition
response.setContentType(getServletContext().getMimeType(filename));
response.setHeader("Content-Disposition", "attachment;filename=" + filename); // 以附件形式打开,不管格式浏览器是否识别
- 处理IE浏览器与Firefox浏览器乱码问题
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"
+ base64Encoder.encode(filename.getBytes("utf-8"))
+ "?=";
} else if (agent.contains("Chrome")) {
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
- 1.创建download2.jsp
<a href=‘${pageContext.request.contextPath}/download?filename=a.bmp‘>a.bmp</a><br>
<a href=‘${pageContext.request.contextPath}/download?filename=a.doc‘>a.doc</a><br>
<a href=‘${pageContext.request.contextPath}/download?filename=a.txt‘>a.txt</a><br>
<a href=‘${pageContext.request.contextPath}/download?filename=tk.mp3‘>tk.mp3</a><br>
- 2.创建DownloadServlet
// 1.得到要下载 的文件名称
String filename = request.getParameter("filename");
//2.判断文件是否存在
File file = new File("d:/upload/" + filename);
if (file.exists())
//3.进行下载
原理:就是通过response获取一个输出流,将要下载的文件内容写回到浏览器端就可以了.
注意:要想通过编程的方式,实现文件下载
- 1.要设置mimetype类型
- resposne.setContextType(String mimeType);
- 问题:怎样可以得到要下载文件的mimeType类型?
- ServletContext.getMimeType(String filename);
- 如果设置了mimeType,浏览器能解析的就直接展示了,不能解析的,直接下载.
- 2.设置一个响应头,设置后的效果,就是无论返回的是否可以被浏览器解析,就是下载 。
- response.setHeader(“content-disposition”,”attachment;filename=下载文件名称”);
- 1.要设置mimetype类型
总结:服务器端编程下载:
- 1.将下载的文件通过resposne.getOutputStream()流写回到浏览器端。
- 2.设置mimeType response.setContentType(getServletContext.getMimeType(String filename));
- 3.设置响应头,目的是永远是下载操作
- response.setHeader(“content-disposition”,”attachment;filename=下载文件名称”);
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.得到要下载 的文件名称
String filename = request.getParameter("filename");
filename = new String(filename.getBytes("iso8859-1"), "utf-8");// 解决中文乱码
// 2.在d:/upload目录下查找这个文件是否存在
File file = new File("d:/upload/" + filename);
if (file.exists()) {
// /文件存在,完成下载
// 下载注意事项1--设置下载文件的mimeType
String mimeType = this.getServletContext().getMimeType(filename);
response.setContentType(mimeType);
String agent = request.getHeader("user-agent");
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"
+ base64Encoder.encode(filename.getBytes("utf-8"))
+ "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
// 下载注意事项2--永远是下载
response.setHeader("content-disposition", "attachment;filename="
+ filename);
FileInputStream fis = new FileInputStream(file); // 读取要下载文件的内容
OutputStream os = response.getOutputStream(); // 将要下载的文件内容通过输出流写回到浏览器端.
int len = -1;
byte[] b = new byte[1024 * 100];
while ((len = fis.read(b)) != -1) {
os.write(b, 0, len);
os.flush();
}
os.close();
fis.close();
} else {
throw new RuntimeException("下载资源不存在.");
}
}
文件下载时的乱码问题
1.关于下载时中文名称资源查找不到
- 原因:
<a href=‘${pageContext.request.contextPath}/download?filename=天空.mp3‘>天空.mp3</a>
- 这是get请求。
- 解决:
String filename = request.getParameter("filename");
filename = new String(filename.getBytes("iso8859-1"),"utf-8");
- 原因:
2.下载文件显示时的中文乱码问题
response.setHeader("content-disposition", "attachment;filename="+filename);
IE:要求filename必须是utf-8码
firefox:要求filename必须是base64编码.
问题:怎样判断浏览器?
String agent=request.getHeader("user-agent");
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"
+ base64Encoder.encode(filename.getBytes("utf-8"))
+ "?=";
}else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
扩展:使用队列来优化递归操作
- 队列特点:先进先出.
- 在jdk中有一个接口Queue 它有一个实现类叫LinkedList它其时就是一个队列。
- 如果要使用队列,插入 offer 获取使用 poll
- 使用队列来优化递归操作:是可以解决目录层次过多问题。
- 因为:递归操作可以理解成是纵向的遍历,如果目录层次比较多,在内存中存储的数据也多,会引起溢出。
- 使用队列,它是横向遍历,一层一层遍历,可以解决目录层次比较多问题。因为使用队列,最多时候在内存中只存储了一层的信息。
- 最常用的就是树型结构。
<!-- 使用队列操作 -->
<%
String path = "D:\\java1110\\workspace\\day22_2\\WebRoot\\upload";
File uploadDirectory = new File(path);
//创建一个队列
Queue<File> queue = new LinkedList<File>();
queue.offer(uploadDirectory);
while (!queue.isEmpty()) { //如果队列不为空
File f = queue.poll(); //从队列中获取一个File
if(f.isDirectory()){//是目录,将目录下所有文件遍历出来,存储到队列中
File[] fs = f.listFiles();
for (int i = 0; i < fs.length; i++) {
queue.offer(fs[i]);
}
}else{
String absolutePath=(f.getAbsolutePath());
String p=absolutePath.substring(absolutePath.lastIndexOf("\\upload"));
out.println("<a href=‘/day22_2"+p+"‘>"+f.getName()+"</a><br>");
}
}
%>
网盘系统
- 需求:
- 1、系统提供一个文件上传功能,在用户上传文件后,文件保存在服务器端指定目录,文件相关信息保存在数据库中
- 2、系统提供一个文件下载功能,将数据表中所有资源信息,显示在页面上,允许用户进行下载
- 1.创建表
create database day23
create table resources(
id int primary key auto_increment,
uuidname varchar(100) unique not null,
realname varchar(40) not null,
savepath varchar(100) not null,
uploadtime timestamp ,
description varchar(255)
);
2.导入jar包和配置文件
- c3p0 commons-fileupload dbutils mysql驱动 jstl
- c3p0-config.xml
3.编码实现上传
- 1.在index.jsp页面添加上传连接
<a href=‘${pageContext.request.contextPath}/upload.jsp‘>上传</a><br>
- 2.创建upload.jsp页面,上传操作浏览器端三个注意事项:
- 1.
method=post
- 2.
encType="multipart/form-data"
- 3.要使用
<input type="file" name=‘f‘>
- 1.
- 1.在index.jsp页面添加上传连接
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
<input type="file" name="f"><br>
描述:<input type="text" name="description"><br>
<input type="submit" value="提交">
</form>
* 3.创建UploadServlet
* 1.上传操作
* commons-fileupload
* 1.DiskFileItemFactory
* 2.ServletFileUpload
* 3.FileItem
* 2.将数据封装,存储到数据库.
* 问题:怎样将数据封装到javaBean?
* 手动创建一个Map<String,String[]>将数据封装到map集合,通过BeanUtils完成数据封装
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Map<String, String[]> map = new HashMap<String, String[]>();
// 1.创建DiskFileItemFactory
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2.创建ServletFileUpload
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置上传文件中文名称乱码
upload.setHeaderEncoding("utf-8");
// upload.isMultipartContent(request)
// 3.得到所有的FileItem
try {
List<FileItem> items = upload.parseRequest(request);
// 遍历items,得到所有的上传信息
for (FileItem item : items) {
if (item.isFormField()) {
// 不是上传组件
map.put(item.getFieldName(),
new String[] { item.getString("utf-8") }); // 封装非上传组件信息
} else {
// 是上传组件
// 得到上传文件名称
String filename = item.getName();
filename = FileUploadUtils.getRealName(filename);
map.put("realname", new String[] { filename }); // 封装上传文件真实名称
// 得到随机名称
String uuidname = FileUploadUtils.getUUIDFileName(filename);
map.put("uuidname", new String[] { uuidname });// 封装上传文件随机名称
// 得到随机目录
String randomDirectory = FileUploadUtils
.getRandomDirectory(filename);
String uploadPath = this.getServletContext().getRealPath(
"/WEB-INF/upload");
File parentDirectory = new File(uploadPath, randomDirectory);
if (!parentDirectory.exists()) {
parentDirectory.mkdirs();
}
map.put("savepath", new String[] { uploadPath
+ randomDirectory });// 封装上传文件保存路径
IOUtils.copy(item.getInputStream(), new FileOutputStream(
new File(parentDirectory, uuidname)));
item.delete();
}
}
// /将数据封装到javaBean
Resource r = new Resource();
BeanUtils.populate(r, map);
// 调用service完成保存数据到db。
ResourceService service = new ResourceService();
service.save(r);
response.sendRedirect(request.getContextPath() + "/index.jsp");
} catch (FileUploadException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
4.下载操作
- 1.在index.jsp页面,下载连接会访问一个servlet,得到所有可以下载的数据,在页面上展示
- 1.index.jsp页面代码
<a href="${pageContext.request.contextPath}/showDownload">下载</a>
- 2.创建ShowDownloadServlet
- 在这个servlet中,查看db,得到所有可以下载的信息
List<Resource> rs = service.findAll();
- 3.创建一个download.jsp页面,展示所有可以下载的信息.
- 1.index.jsp页面代码
2.在download.jsp,点击下载时,传递的是要下载文件的id。
<a href=‘${pageContext.request.contextPath}/download?id=${r.id}‘>下载</a>
3.创建一个DownloadServlet
- 1.查询数据库,得到要下载的文件的相关信息
- 2.下载操作
- 1.在index.jsp页面,下载连接会访问一个servlet,得到所有可以下载的数据,在页面上展示
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1.得到id
String id = request.getParameter("id");
// 2.调用service,得到Resource对象.
ResourceService service = new ResourceService();
try {
Resource r = service.findById(id);
File file = new File(r.getSavepath(), r.getUuidname());
if (file.exists()) {
// 资源存在
String filename = r.getRealname();
// 下载注意事项1--设置下载文件的mimeType
String mimeType = this.getServletContext()
.getMimeType(filename);
response.setContentType(mimeType);
String agent = request.getHeader("user-agent");
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"
+ base64Encoder.encode(filename.getBytes("utf-8"))
+ "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
// 下载注意事项2--永远是下载
response.setHeader("content-disposition",
"attachment;filename=" + filename);
byte[] b = FileUtils.readFileToByteArray(file); // 将指定文件读取到byte[]数组中.
response.getOutputStream().write(b);
} else {
throw new RuntimeException("资源不存在");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
以上是关于Java进阶学习第二十二天——上传与下载的主要内容,如果未能解决你的问题,请参考以下文章