文件上传:将本地文件通过流的方式上传到服务器,常用的文件上传方法有很多,本次主要介绍的文件上传技术是FileUpLoad.文件上传三要素:1、表单提交方式为post. 2、需要有属性,name元素和值。3、表单enctype="multipart/form-data"。文件下载:将服务器的文件通过流写到客户端。文件下载的方式主要为超链接下载和手动编写代码方式下载。
目录
首先创建web项目,配置tomcat服务器,导入文件上传所需jar包,具体如下:

web项目中创建文件上传的upload.jsp页面,具体如下:
- <%--
- Created by IntelliJ IDEA.
- User: nuist__NJUPT
- Date: 2022-08-15
- Time: 16:53
- To change this template use File | Settings | File Templates.
- --%>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <form action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data">
- 文件描述:<input type="text" name="info">br>
- 文件上传:<input type="file" name="upload">br>
- <input type="submit" value="文件上传">
- form>
- body>
- html>
处理upload.jsp表单提交的Servlet类,具体如下:
- import org.apache.commons.fileupload.FileItem;
- import org.apache.commons.fileupload.FileUploadException;
- import org.apache.commons.fileupload.disk.DiskFileItemFactory;
- import org.apache.commons.fileupload.servlet.ServletFileUpload;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.*;
- import java.util.List;
-
- public class UploadServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- boolean flag = ServletFileUpload.isMultipartContent(req) ;
- if(!flag){
- //如果表单不是enctype="multipart/form-data"
- req.setAttribute("msg","表单设置不正确");
- req.getRequestDispatcher("/jsp/upload.jsp").forward(req,resp);
- }
- try {
- //1.创建磁盘文件项工厂
- DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
- diskFileItemFactory.setSizeThreshold(3*1024*1024); //设置缓冲区的大小为3MB
- //设置文件的临时路径
- String temp = getServletContext().getRealPath("/temp") ;
- diskFileItemFactory.setRepository(new File(temp));
- //2.创建一个核心解析类
- ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory) ;
- //设置上传文件的大小为5MB
- // fileUpload.setSizeMax(5*1024*1024);
- //3.利用核心类解析Request,解析后会得到多个部分,存入list集合中
- List
list = fileUpload.parseRequest(req) ; - //4.遍历文件项,判断文件项是普通项,还是文件上传项
- for(FileItem fileItem : list){
- if(fileItem.isFormField()){
- //接收普通项的值
- String name = fileItem.getFieldName() ;
- String value = fileItem.getString("UTF-8") ;
- System.out.println(name + " "+ value);
- }else{
- //文件上传项目
- //获得文件上传项的文件名及文件内容
- String filename = fileItem.getName() ;
- int index = filename.lastIndexOf("\\") ;
- if(index != -1){
- //老版本浏览器
- filename = filename.substring(index+1) ;
- }
- InputStream is = fileItem.getInputStream() ;
- //获得文件上传的磁盘绝对路径
- String realPath = getServletContext().getRealPath("/upload");
- //创建一个输出流,写入到真实的路径中
- OutputStream os = new FileOutputStream(realPath+"/"+filename) ;
- //两个流实现对接
- int len = 0 ;
- byte [] bytes = new byte[1024] ;
- while((len=is.read(bytes)) != -1){
- os.write(bytes,0,len);
- }
- is.close();
- os.close();
- }
- // fileItem.delete(); //删除临时文件
- }
- } catch (FileUploadException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req,resp);
- }
- }
在web.xml文件中对使用的Servlet的名称及路径进行配置,具体如下:
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
- <servlet>
- <servlet-name>UploadServletservlet-name>
- <servlet-class>com.controller.UploadServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>UploadServletservlet-name>
- <url-pattern>/UploadServleturl-pattern>
- servlet-mapping>
-
- web-app>
JavaScript控制多个文件上传,在原来的基础上,编写多文件上传页面jsp如下:
- <%--
- Created by IntelliJ IDEA.
- User: nuist__NJUPT
- Date: 2022-08-15
- Time: 16:53
- To change this template use File | Settings | File Templates.
- --%>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- <script>
- function add() {
- //获得id为div1的元素
- var div1Element = document.getElementById("div1") ;
- div1Element.innerHTML += "" ;
- }
- function del(who) {
- //每次找到父类后将自身移除
- who.parentNode.parentNode.removeChild(who.parentNode) ;
- }
- script>
- head>
- <body>
- <h1>多文件上传h1>
- <form action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data">
- 文件描述:<input type="button" value="添加" onclick="add()">br>
- <input type="submit" value="文件上传"><br/>
- <div id="div1">
-
- div>
- form>
- body>
- html>
防止不同浏览器上传重名的文件将原始的文件覆盖掉,故使用工具类生成唯一的文件名,工具类如下:
- import java.util.UUID;
-
- /**
- * 文件上传的工具类
- */
- public class UploadUtils {
- public static String getUuidFilename(String filename) {
- //获得文件的扩展名
- int index = filename.lastIndexOf(".");
- String extension = filename.substring(index);
- return UUID.randomUUID().toString().replace("-", "") + extension;
- }
- }
在servlet中使用该工具类对上传文件生成唯一的文件名,具体如下:
- import com.utils.UploadUtils;
- import org.apache.commons.fileupload.FileItem;
- import org.apache.commons.fileupload.FileUploadException;
- import org.apache.commons.fileupload.disk.DiskFileItemFactory;
- import org.apache.commons.fileupload.servlet.ServletFileUpload;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.*;
- import java.util.List;
-
- public class UploadServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- boolean flag = ServletFileUpload.isMultipartContent(req) ;
- if(!flag){
- //如果表单不是enctype="multipart/form-data"
- req.setAttribute("msg","表单设置不正确");
- req.getRequestDispatcher("/jsp/upload.jsp").forward(req,resp);
- }
- try {
- //1.创建磁盘文件项工厂
- DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
- diskFileItemFactory.setSizeThreshold(3*1024*1024); //设置缓冲区的大小为3MB
- //设置文件的临时路径
- String temp = getServletContext().getRealPath("/temp") ;
- diskFileItemFactory.setRepository(new File(temp));
- //2.创建一个核心解析类
- ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory) ;
- //设置上传文件的大小为5MB
- // fileUpload.setSizeMax(5*1024*1024);
- //3.利用核心类解析Request,解析后会得到多个部分,存入list集合中
- List
list = fileUpload.parseRequest(req) ; - //4.遍历文件项,判断文件项是普通项,还是文件上传项
- for(FileItem fileItem : list){
- if(fileItem.isFormField()){
- //接收普通项的值
- String name = fileItem.getFieldName() ;
- String value = fileItem.getString("UTF-8") ;
- System.out.println(name + " "+ value);
- }else{
- //文件上传项目
- //获得文件上传项的文件名及文件内容
- String filename = fileItem.getName() ;
- int index = filename.lastIndexOf("\\") ;
- if(index != -1){
- //老版本浏览器
- filename = filename.substring(index+1) ;
- }
- String filename1 = UploadUtils.getUuidFilename(filename) ;
- InputStream is = fileItem.getInputStream() ;
- //获得文件上传的磁盘绝对路径
- String realPath = getServletContext().getRealPath("/upload");
- //创建一个输出流,写入到真实的路径中
- OutputStream os = new FileOutputStream(realPath+"/"+filename1) ;
- //两个流实现对接
- int len = 0 ;
- byte [] bytes = new byte[1024] ;
- while((len=is.read(bytes)) != -1){
- os.write(bytes,0,len);
- }
- is.close();
- os.close();
- }
- // fileItem.delete(); //删除临时文件
- }
- } catch (FileUploadException e) {
- e.printStackTrace();
- }
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req,resp);
- }
- }
文件下载方式1:超链接下载方式,下载服务器在download文件夹下的资源,代码如下:
- <%--
- Created by IntelliJ IDEA.
- User: nuist__NJUPT
- Date: 2022-08-15
- Time: 20:22
- To change this template use File | Settings | File Templates.
- --%>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
- <h1>文件下载:超链接的方式h1>
- <h3><a href="${ pageContext.request.contextPath }/download/bootstrap-3.4.1-dist.zip">bootstrap.zipa>h3>
- <h3><a href="${ pageContext.request.contextPath }/download/a.docx">a.docxa>h3>
- body>
- html>
我们使用手动编写Servlet,将资源交给Servlet下载,首先在jsp页面将资源文件转给Servlet,代码如下:
- <%--
- Created by IntelliJ IDEA.
- User: nuist__NJUPT
- Date: 2022-08-15
- Time: 20:22
- To change this template use File | Settings | File Templates.
- --%>
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Titletitle>
- head>
- <body>
-
- <h1>文件下载:手动编程下载的方式h1>
- <h3><a href="${ pageContext.request.contextPath }/DownloadServlet?filename=bootstrap-3.4.1-dist.zip">bootstrap.zipa>h3>
- <h3><a href="${ pageContext.request.contextPath }/DownloadServlet?filename=a.docx">a.docxa>h3>
- body>
- html>
然后编写用于处理文件下载的Servlet类,具体如下:
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
-
- public class DownloadServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- //接收参数
- String filename = request.getParameter("filename") ;
- //下载,设置两个头和一个流
- //设置Content-type
- String type = request.getServletContext().getMimeType(filename) ;
- response.setContentType(type);
- //设置Content-Disposition
- response.setHeader("Content-Disposition","attachment;filename="+filename);
- //设置一个代表文件的输入流
- String path = request.getServletContext().getRealPath("/download" ) ;
- InputStream is = new FileInputStream(path+"/"+filename) ;
- OutputStream os = response.getOutputStream() ;
- //两个流的对接
- int len = 0 ;
- byte [] bytes = new byte[1024] ;
- while((len=is.read(bytes)) != -1){
- os.write(bytes,0,len);
- }
- is.close();
- os.close();
-
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req,resp);
- }
- }
最后需要在web.xml文件中配置Servlet,具体如下:
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
- <servlet>
- <servlet-name>DownloadServletservlet-name>
- <servlet-class>com.controller.DownloadServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>DownloadServletservlet-name>
- <url-pattern>/DownloadServleturl-pattern>
- servlet-mapping>
- web-app>
对于包含中文名称的文件,防止乱码,需要识别浏览器类型,并设置为UTF-8编码,具体的Servlet如下所示:
- import com.utils.DownloadUtils;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.*;
- import java.net.URLEncoder;
-
- public class DownloadServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- //接收参数
- String filename = new String(request.getParameter("filename").getBytes("ISO-8859-1"),"UTF-8");
- //下载,设置两个头和一个流
- //设置Content-type
- String type = request.getServletContext().getMimeType(filename) ;
- response.setContentType(type);
- //设置一个代表文件的输入流
- String path = request.getServletContext().getRealPath("/download" ) ;
- File file = new File(path+"/"+filename);
-
- // 判断浏览器的类型:
- String agent = request.getHeader("User-Agent");
- if(agent.contains("Firefox")){
- // 使用的是Firefox
- filename = DownloadUtils.base64EncodeFileName(filename);
- }else{
- // IE或者其他的浏览器
- filename = URLEncoder.encode(filename, "UTF-8");
- }
-
- //设置Content-Disposition
- response.setHeader("Content-Disposition","attachment;filename="+filename);
-
- InputStream is = new FileInputStream(file) ;
- OutputStream os = response.getOutputStream() ;
- //两个流的对接
- int len = 0 ;
- byte [] bytes = new byte[1024] ;
- while((len=is.read(bytes)) != -1){
- os.write(bytes,0,len);
- }
- is.close();
- os.close();
-
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req,resp);
- }
- }
当然这个servlet中对于火狐浏览器的编码问题使用了一个工具类,具体如下:
- import java.io.UnsupportedEncodingException;
-
- import sun.misc.BASE64Encoder;
-
- public class DownloadUtils {
- public static String base64EncodeFileName(String fileName) {
- BASE64Encoder base64Encoder = new BASE64Encoder();
- try {
- return "=?UTF-8?B?"
- + new String(base64Encoder.encode(fileName
- .getBytes("UTF-8"))) + "?=";
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
- }
定义一个jsp页面用于在浏览器显示目录中的所有文件。
- <%--
- Created by IntelliJ IDEA.
- User: nuist__NJUPT
- Date: 2022-08-16
- Time: 9:33
- To change this template use File | Settings | File Templates.
- --%>
- <%@page import="java.io.File"%>
- <%@page import="java.util.*"%>
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>Insert title heretitle>
- head>
- <body>
- <h1>树形遍历h1>
- <%
- // 1.创建一个队列:
- Queue<File> queue = new LinkedList<File>();
- // 2.先将跟节点入队:
- File root = new File("E://resource");
- queue.offer(root);
- // 判断这个队列是否为空,不为空需要进行遍历:
- while(!queue.isEmpty()){
- // 将跟节点出队:
- File file = queue.poll();
- // 获得跟节点下的所有子节点:
- File[] files = file.listFiles();
- // 遍历所有子节点:
- for(File f:files){
- // 判断该节点是否为叶子节点:
- if(f.isFile()){
- %>
- <h4><a href="${ pageContext.request.contextPath }/DownloadListServlet?filename=<%=f.getCanonicalPath()%>"><%= f.getName() %>a>h4>
- <%
- }else{
- queue.offer(f);
- }
- }
- }
- %>
- body>
- html>
手动编写servlet处理文件下载问题,具体如下:
- import com.utils.DownloadUtils;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.*;
- import java.net.URLEncoder;
-
- public class DownloadListServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // 接收参数:
- String path = request.getParameter("filename");
- if(path != null){
- path = new String(path.getBytes("ISO-8859-1"),"UTF-8");
- }
- File file = new File(path);
- // 实现文件下载:设置两个头和一个流:
- // 获得文件名
- String filename = file.getName();
- response.setContentType(getServletContext().getMimeType(filename));
- // 设置另一个头:
- String agent = request.getHeader("User-Agent");
- if(agent.contains("Firefox")){
- filename = DownloadUtils.base64EncodeFileName(filename);
- }else{
- filename = URLEncoder.encode(filename, "UTF-8");
- filename = filename.replace("+", " ");
- }
- response.setHeader("Content-Disposition", "attachment;filename="+filename);
- // 设置输入流:
- InputStream is = new FileInputStream(file);
- OutputStream os = response.getOutputStream();
- int len = 0;
- byte[] b = new byte[1024];
- while((len = is.read(b))!=-1){
- os.write(b, 0, len);
- }
- is.close();
- }
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- doGet(req,resp);
- }
- }
在web.xml中配置servlet,具体如下:
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
- <servlet>
- <servlet-name>DownloadListServletservlet-name>
- <servlet-class>com.controller.DownloadListServletservlet-class>
- servlet>
- <servlet-mapping>
- <servlet-name>DownloadListServletservlet-name>
- <url-pattern>/DownloadListServleturl-pattern>
- servlet-mapping>
- web-app>