简介:文件上传和下载是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>密&nbsp;&nbsp;&nbsp;&nbsp;码:<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文件上传和下载的更多相关文章

  1. java文件上传和下载

    简介 文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到 ...

  2. Java 文件上传与下载、email

    1. 文件上传与下载 1.1 文件上传 文件上传,要点: 前台: 1. 提交方式:post 2. 表单中有文件上传的表单项: <input type="file" /> ...

  3. Java文件上传与下载

    文件上传与下载可谓上网中的常见现象.apache为我们准备了用于文件上传与下载的两个jar包(commons-fileupload-1.2.1.jar,commons-io-1.4.jar).我们在w ...

  4. selenium java 文件上传、下载

    1.webdriver对页面文件的下载 我们一般操作浏览器下载时会让我们选择下载的目录然后经过一系列操作后才进行文件下载操作,但是用webdriver不能按这样的方式操作.经过查询资料找到了如下的实现 ...

  5. java文件上传、下载、图片预览

    多文件保存到本地: @ResponseBody    @RequestMapping(value = "/uploadApp",produces = { "applica ...

  6. 2013第38周日Java文件上传下载收集思考

    2013第38周日Java文件上传&下载收集思考 感觉文件上传及下载操作很常用,之前简单搜集过一些东西,没有及时学习总结,现在基本没啥印象了,今天就再次学习下,记录下自己目前知识背景下对该类问 ...

  7. SpringMVC文件上传和下载的实现

    SpringMVC通过MultipartResolver(多部件解析器)对象实现对文件上传的支持. MultipartResolver是一个接口对象,需要通过它的实现类CommonsMultipart ...

  8. java web学习总结(二十四) -------------------Servlet文件上传和下载的实现

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  9. java web(四)文件上传与下载

     一.文件上传原理 1.在TCP/IP中,最早出现的文件上传机制是FTP ,它是将文件由客户端发送到服务器的标准机制:但是在jsp使用过程中不能使用FTP方法上传文件,这是由jsp运行机制所决定. 通 ...

随机推荐

  1. Start and Stop Bitbucket Server

    Starting and stopping Bitbucket Server This page describes the various ways you can start or stop Bi ...

  2. AT2672 Coins

    传送门 按理说想到转化问题之后就不难了吧,可是我还是不会写 一个很容易想到的转化就是差分,将银币数和铜币数都减去金币数,这样就转化为\(x+y+z\)个钱币选\(y\)个银币和\(z\)个铜币的最大数 ...

  3. Swift几行代码解决UITableView空数据视图问题

    tableView空数据问题 一般项目中tableView若数据为空时会有一个提示示意图 为了更好的管理这种提示示意图,笔者利用extension进行了简单的拓展 解决思路 利用swift面向协议的特 ...

  4. spring boot war

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...

  5. JavaScript和jquery中的宽度

    Javascript: 网页可见区域宽: document.body.clientWidth 网页可见区域高: document.body.clientHeight 网页可见区域宽: document ...

  6. spring mvc做上传图片,文件小于10k就不生成临时文件了

    这是spring-mvc.xml中的 <bean id="multipartResolver" class="org.springframework.web.mul ...

  7. angularjs 使用angular-sortable-view实现拖拽效果(包括拖动完成后的方法使用)

    首先还是看效果图吧,方便大家可以快速得知是否是自己需要的功能:(抱歉电脑还未安装动图软件,先用.png) 如果上图是你需要的功能效果图,那么请往下看,我有写出来例子哦~ 使用这个插件有几个好处,首先: ...

  8. maven 引入本地项目jar报红线错误解决方法

    问题:本地创建了2个项目,A和B,A引入B,A的pom如下: <dependency> <groupId>com.ebc</groupId> <artifac ...

  9. @Requestbody@ApiParam @PathVariable @RequestParam三者区别

    一.问题描述 由于项目是前后端分离,因此后台使用的是spring boot,做成微服务,只暴露接口.接口设计风格为restful的风格,在get请求下,后台接收参数的注解为RequestBody时会报 ...

  10. JS——jquery UI

    1. draggable() 滑动条demo: <!DOCTYPE html> <html lang="en"> <head> <meta ...