common-fileupload组件实现java文件上传和下载
简介:文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
文件上传
(1)文件上传前端界面(fileupload.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<form action="FileUpload" method="post" enctype="multipart/form-data">
<p><label>用户名:<input type="text" name="username"></label></p>
<p><label>密 码:<input type="password" name="pwd"></label></p>
<p><input type="file" name="upfile"></p>
<input type="submit" value="提交">
</form>
</body>
</html>
[注]:在文件上传的页面要用enctype="multipart/form-data" method="post"来表示进行文件上传
(2)文件上传细节
上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的:
(2.1)、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
(2.2)、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
(2.3)、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
(2.4)、要限制上传文件的最大值。
(2.5)、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
(3)处理文件上传的servlet
package com.etc.utils; import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.UUID; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload; @WebServlet("/FileUpload")
public class FileUpload extends HttpServlet {
private static final long serialVersionUID = 1L; public FileUpload() {
super();
} protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String filedName = ""; // 1、创建工厂类:DiskFileItemFactory factory=new DiskFileItemFactory();
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2、创建解析器:ServletFileUpload upload=new ServletFileUpload(factory);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8"); // 设置缓冲区大小与临时文件目录
factory.setSizeThreshold(1024 * 1024 * 10);
File fileDir = new File("e:\\upload");
if (!fileDir.exists())
fileDir.mkdirs();
// 设置文件存储仓库
factory.setRepository(fileDir);
// 设置单个文件大小限制
upload.setFileSizeMax(1024 * 1024 * 10);
// 设置所有文件总和大小限制
upload.setSizeMax(1024 * 1024 * 100); // 3、使用解析器解析request对象:List<FileItem> list=upload.parseRequest(request);
/**
* FileItem
* String getFieldName():获取表单项的name的属性值。
* String getName():获取文件字段的文件名。如果是普通字段,则返回null
* String getString():获取字段的内容。如果是普通字段,则是它的value值;如果是文件字段,则是文件内容。
* String getContentType():获取上传的文件类型,例如text/plain、image。如果是普通字段,则返回null。
* long getSize():获取字段内容的大小,单位是字节。
* boolean isFormField():判断是否是普通表单字段,若是,返回true,否则返回false。
* InputStream getInputStream():获得文件内容的输入流。如果是普通字段,则返回value值的输入流
*/
try {
List<FileItem> list = upload.parseRequest(request);
System.out.println(list);
for (FileItem fileItem : list) {
/*
* 对文件进行处理
*/
if (!fileItem.isFormField() && fileItem.getName() != null && !"".equals(fileItem.getName())) {
String fileName = fileItem.getName();
String uuid = UUID.randomUUID().toString();
//获取文件的后缀名
//String suffix = fileName.substring(fileName.lastIndexOf("."));
//获取文件上传目录路径,在项目部署路径下的upload目录里。若想让浏览器不能直接访问到图片,可以放在WEB-INF下
String uploadPath = request.getSession().getServletContext().getRealPath("/upload");
File file = new File(uploadPath);
file.mkdirs();
//将文件写入对应路径,并对文件进行重命名
fileItem.write(new File(uploadPath, uuid + "_"+ fileName));
}
/*
* 对表中的普通字段进行处理
*/
if(fileItem.isFormField()) {
filedName = fileItem.getFieldName();
String username = null;
String pwd = null;
if("username".equals(filedName)) {
username = fileItem.getString("UTF-8");
out.println("用户名:" + username);
}
if("pwd".equals(filedName)) {
pwd = fileItem.getString("UTF-8");
out.println("\t密码:" + pwd);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
文件下载
(1)列出提供下载的文件资源
要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件。
package com.etc.utils; import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; @WebServlet("/FileDownLoad")
public class FileDownLoad extends HttpServlet {
private static final long serialVersionUID = 1L;
public FileDownLoad() {
super();
} protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
// 获取上传文件的目录
String uploadFilePath = this.getServletContext().getRealPath("/upload");
// 储存要下载的文件名
Map<String, String> fileMap = new HashMap<String, String>();
// 递归遍历fileMap目录下的所有文件和目录,将文件储存到map集合中
fileList(new File(uploadFilePath),fileMap);
//将Map集合发送到listfile.jsp页面进行显示
request.setAttribute("fileMap", fileMap);
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
} public void fileList(File file, Map<String,String> fileMap) {
// 如果file代表的不是一个文件而是一个目录
if (!file.isFile()) {
File[] files = file.listFiles();
for (File file2 : files) {
fileList(file2, fileMap);
}
} else {
/**
* 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
* file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_timer.avi
* 那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到timer.avi部分
*/
String realName = file.getName().substring(file.getName().lastIndexOf("_")+1);
System.out.println(realName);
fileMap.put(file.getName(), realName);
}
} protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
(2)创建显示文件列表的jsp界面(listfile.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link href="css/bootstrap.css" rel="stylesheet">
<title>下载文件显示界面</title>
</head>
<body>
<div class="container">
<table class="table table-bordered">
<caption>文件下载列表</caption>
<c:forEach var="me" items="${requestScope.fileMap}">
<tr>
<c:url value="DownLoadServlet" var="downurl">
<c:param name="filename" value="${me.key}"></c:param>
</c:url> <td>${me.value}</td><td><a href="${downurl}">下载</a></td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
(3)实现文件下载的servlet
DownLoadServlet的代码如下:
package com.etc.utils; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; @WebServlet("/DownLoadServlet")
public class DownLoadServlet extends HttpServlet {
private static final long serialVersionUID = 1L; public DownLoadServlet() {
super();
// TODO Auto-generated constructor stub
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("filename");
//获取文件路径
String fileSaveRootPath = this.getServletContext().getRealPath("/upload");
//获取真实的文件名
String realname = fileName.substring(fileName.indexOf("_")+1);
//得到要下载的文件
File file = new File(fileSaveRootPath+File.separator+fileName);
//如果文件不存在
if(!file.exists()) {
request.setAttribute("msg", "您要下载的文件已被删除!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//设置响应头,控制浏览器下载该文件 可通过URLEncoder.encode(realname, "UTF-8")实现对下载的文件进行重命名
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
//获取输入输出流
InputStream is = new FileInputStream(file);
OutputStream os = response.getOutputStream();
//调用common-io下面的静态方法,用于实现文件复制(从服务器端复制到本地)
IOUtils.copy(is, os);
is.close();
} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
文件上传下载还能进行很多优化,可参考博文
common-fileupload组件实现java文件上传和下载的更多相关文章
- java文件上传和下载
简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到 ...
- Java 文件上传与下载、email
1. 文件上传与下载 1.1 文件上传 文件上传,要点: 前台: 1. 提交方式:post 2. 表单中有文件上传的表单项: <input type="file" /> ...
- Java文件上传与下载
文件上传与下载可谓上网中的常见现象.apache为我们准备了用于文件上传与下载的两个jar包(commons-fileupload-1.2.1.jar,commons-io-1.4.jar).我们在w ...
- selenium java 文件上传、下载
1.webdriver对页面文件的下载 我们一般操作浏览器下载时会让我们选择下载的目录然后经过一系列操作后才进行文件下载操作,但是用webdriver不能按这样的方式操作.经过查询资料找到了如下的实现 ...
- java文件上传、下载、图片预览
多文件保存到本地: @ResponseBody @RequestMapping(value = "/uploadApp",produces = { "applica ...
- 2013第38周日Java文件上传下载收集思考
2013第38周日Java文件上传&下载收集思考 感觉文件上传及下载操作很常用,之前简单搜集过一些东西,没有及时学习总结,现在基本没啥印象了,今天就再次学习下,记录下自己目前知识背景下对该类问 ...
- SpringMVC文件上传和下载的实现
SpringMVC通过MultipartResolver(多部件解析器)对象实现对文件上传的支持. MultipartResolver是一个接口对象,需要通过它的实现类CommonsMultipart ...
- java web学习总结(二十四) -------------------Servlet文件上传和下载的实现
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- java web(四)文件上传与下载
一.文件上传原理 1.在TCP/IP中,最早出现的文件上传机制是FTP ,它是将文件由客户端发送到服务器的标准机制:但是在jsp使用过程中不能使用FTP方法上传文件,这是由jsp运行机制所决定. 通 ...
随机推荐
- 求第 i 个素数 Meissel Lehmer Algorithm + 二分 【模板】
1473: L先生与质数V3 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1348 Solved: 147 [Submit][Status][Web ...
- thinkphp5实现文章上一篇,下一篇
写在控制器 //列表是按照根据id降序排列的,所以上一篇 $prv=Db::table('qy_article')->where('at_id','>',$at_id)->where ...
- 20165224 陆艺杰 Exp 8 Web基础
.基础问题回答 (1)什么是表单 html的一个控件 表单在网页中主要负责数据采集功能 (2)浏览器可以解析运行什么语言 html xml jsp php python 等 (3)WebServer支 ...
- PAT甲级——1099 Build A Binary Search Tree (二叉搜索树)
本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/90701125 1099 Build A Binary Searc ...
- 16.Ubuntu LTS 16.04安装搜狗输入法全过程记录(纯新手)
这是我第四次打算转到Ubuntu上了,应该不会像以前那样装个系统就拜拜了.打算先把C和Vim重新学起来,数据结构那本书看完写完,第二步是学python和算法导论,暂定如此. 昨天晚上系统装完以后想着要 ...
- tomcat7 开机自启动(转)
转自 http://blog.csdn.net/rainyspring4540/article/details/51861079 环境:win7 tomcat7 开机自启动: 使用管理员打开命令提示 ...
- *.rpm is not signed解决
1.# yum install qemu*报错如下:Package qemu-kvm-tools-0.12.1.2-2.113.el6.x86_64.rpm is not signed2.解决# vi ...
- Java正则表达式—小应用—简易爬虫
在上一篇中,学习了正则表达式的四个功能.即匹配.分割.替换.获取. 利用获取功能,可以实现简单的网页爬虫. 4,获取:将字符串中的符合规则的子串取出. 获取功能的操作步骤: 1,将正则表达式 ...
- [转]latex符号
常用数学符号的 LaTeX 表示方法 (以下内容主要摘自“一份不太简短的 LATEX2e 介绍”) 1.指数和下标可以用^和_后加相应字符来实现.比如: 2.平方根(square root)的输入命令 ...
- 跨平台移动开发phonegap/cordova 3.3全系列教程-结合asp.net/jqmboile
遠程app配置 把編譯後的www資料夾,復制到遠程地址(目錄結構不要改變), 例如:建議使用app-framework 1.加入jquery mobile1.4点击打开链接 2.加入app-frame ...