简介:文件上传和下载是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. nagios客户端之nrpe3.2.1安装(Ubuntu)

    1.删除dpkg安装的nrpedpkg -l | grep nrpedkpg -P nagios-nrpe-server 2.ubuntu下nrpe3.2.1安装 下载nrpe3.2.1的源码包:ht ...

  2. Django基础(5) ----基于双下划线的跨表查询,聚合查询,分组查询,F查询,Q查询

    一.基于双下划线的跨表查询 Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系.要做跨关系查询,就使用两个下划线来链接模型(mode ...

  3. TOMCAT热部署 catalina.home catalina.base

    catalina.home 一台机器通常只有一个, 指向Tomcat的安装目录 catalina.base  一台机器可以启动多个Context, 每个Context对应一个catalina.base ...

  4. LeetCode 233 Number of Digit One 某一范围内的整数包含1的数量

    Given an integer n, count the total number of digit 1 appearing in all non-negative integers less th ...

  5. Gym 101047K Training with Phuket's larvae

    http://codeforces.com/gym/101047/problem/K 题目:给定n<=2000条绳子,要你找出其中三条,围成三角形,并且要使得围成的三角形面积最小 思路: 考虑一 ...

  6. lazy load的一些网址

    http://www.gayadesign.com/scripts/queryLoader/ http://www.oschina.net/p/queryloader http://www.cnblo ...

  7. SpringBoot | 第十章:Swagger2的集成和使用

    前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成.现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的沟 ...

  8. 两道sql面试题

    两道sql面试题:    1. 数据库表A的数据如下:             year   quarter             2001      1             2001      ...

  9. Ubuntu 14.04上安装Riak

    一.安装riak   1. 安装包:riak_2.0.2-1_amd64.deb    路    径:~/software/riak_2.0.2-1_amd64.deb 2. 安装riak     $ ...

  10. ngnix反向代理

    https://blog.csdn.net/sherry_chan/article/details/79055211