看完再也不担心不会文件的上传与下载了!(建议收藏)

网友投稿 847 2022-05-28

一、文件的上传

将用户本地磁盘中的文件提交保存到服务器中的磁盘上。

1.1、存在的问题.

我们要做文件上传,一般的步骤是:

要有一个 form 标签,method=post 请求。因为get请求里面限制了大小。

form 标签的 encType 属性值必须为 multipart/form-data 值。

在 form 标签中使用 input type=file 添加上传的文件。

编写服务器代码(Servlet 程序)接收,处理上传的数据。

encType=multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼

接,然后以二进制流的形式发送给服务器。

我们通过写代码可以发现,enctype=“multipart/form-data” 提交的数据,getParameter() 无法获取到。

1.2、Servlet3.0 文件上传

既然文件上传如此头疼,那么总该有人挺身而出帮我们解决这个难题。Servlet 3.0 提供了文件上传操作功能,而且使用也非常简单。

我们只需要给 Servlet 贴一个注解 @MultipartConfig然后使用getPart()获取请求中指定 name 的文件到 Part 对象,就可以使用它的API来进行操作文件了。

1.3、API

HttpServletRequest 提供了两个方法用于从请求中解析上传的文件。

Part中常用的方法:

1.4、代码

package com.servlet; import java.io.IOException; import java.net.http.HttpClient; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; /** * @author Xiao_Lin * @date 2021/1/20 9:26 */ @WebServlet("/fileUpload") @MultipartConfig public class FileUploadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 普通的参数还是使用原来的接收方式 String username = req.getParameter("username"); // 文件数据的获取 Part part = req.getPart("headImg"); //保存到磁盘,参数名称为盘符+文件名+后缀名(自己命名) part.write("d:/headimg.jpg");

<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>

Hello World!

用户名: 上传文件:

二、文件上传拓展

看完再也不担心不会文件的上传与下载了!(建议收藏)

2.1、获取上传文件名

我们可以使用可使用 Part对象的API来获取。

package com.servlet; import java.io.IOException; import java.net.http.HttpClient; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; /** * @author Xiao_Lin * @date 2021/1/20 9:26 */ @WebServlet("/fileUpload") @MultipartConfig public class FileUploadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 普通的参数还是使用原来的接收方式 String username = req.getParameter("username"); // 文件数据的获取 Part part = req.getPart("headImg"); // 保存到磁盘,参数名称为盘符+文件名+后缀名(自动获取文件名) part.write("d:/"+part.getSubmittedFileName()); } }

2.2、使用UUID生成文件名

若上传得文件名相同会导致覆盖服务器之前已上传的的文件,我们的解决方法就是自己给文件起一个唯

一的名称,确保不被覆盖,这里我们使用的是 UUID。

package com.servlet; import java.io.IOException; import java.net.http.HttpClient; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; /** * @author Xiao_Lin * @date 2021/1/20 9:26 */ @WebServlet("/fileUpload") @MultipartConfig public class FileUploadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 文件数据的获取 Part part = req.getPart("headImg"); //获取上传的文件名 String realName = part.getSubmittedFileName(); //拿到文件的拓展名 String ext = realName.substring(realName.lastIndexOf(".")); //生成唯一的UUID,保证不会重复 String fileNewName = UUID.randomUUID().toString()+ext; part.write("d://"+fileNewName); } }

注意:在tomcat7 的环境下就没有part.getSubmittedFileName()这一方法,无法直接获取文件名,如果使用的是Tomcat7插件或者是Tomcat8以下的版本,需要换方法。不然会报错。

String cd = part.getHeader("Content-Disposition"); //截取不同类型的文件需要自行判断 String filename = cd.substring(cd.lastIndexOf("=")+2, cd.length()-1);

2.3、文件保存位置问题

文件在磁盘某个位置,不在项目下,无法使用 HTTP 协议访问,所以要把用户上传的文件存放到项目中

才可通过 HTTP 协议来访问,且保存的位置路径不可以写绝对路径,那么我们该如何进行访问呢?

我们可以通过ServletContext 对象的 getRealPath("项目中保存上传文件的文件夹的相对路径") 来获取其的绝对路径。

我们在webapps目录下新建一个upload用来存放文件。

package com.servlet; import java.io.IOException; import java.net.http.HttpClient; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; /** * @author Xiao_Lin * @date 2021/1/20 9:26 */ @WebServlet("/fileUpload") @MultipartConfig public class FileUploadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 文件数据的获取 Part part = req.getPart("headImg"); String cd = part.getHeader("Content-Disposition"); //获取上传的文件名 String realName = cd.substring(cd.lastIndexOf("=")+2, cd.length()-1); //拿到文件的拓展名 String ext = realName.substring(realName.lastIndexOf(".")); //生成唯一的UUID,保证不会重复 String fileNewName = UUID.randomUUID().toString()+ext; // 获取项目下的 upload 目录的绝对路径,拼接成文件的保存路径(maven项目需要用tomcat7才可以) String realPath = req.getServletContext().getRealPath("/upload") +"/"+ fileNewName; part.write(realPath); } }

2.4、文件类型的约束

限制用户恶意上传文件,比如要让用户上传头像,而用户却上传一个非图片文件,比如 JSP 文件。

package com.servlet; import java.io.IOException; import java.net.http.HttpClient; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; /** * @author Xiao_Lin * @date 2021/1/20 9:26 */ @WebServlet("/fileUpload") @MultipartConfig public class FileUploadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 文件数据的获取 Part part = req.getPart("headImg"); System.out.println(part.getContentType()); // 如果上传的文件不是图片(文件扩展名不是以image开头的就不是图片) if (!part.getContentType().startsWith("image/")) { req.setAttribute("msg","请上传图片"); req.getRequestDispatcher("/index.jsp").forward(req, resp); return; } } }

2.5、文件的大小约束

文件上传限制大小可提高服务器硬盘的使用率,防止用户恶意上传文件造成服务器磁盘资源紧张。我们可以通过设置 @MutipartConfig的属性做限制,他有两个属性:

maxFileSize:单个上传文件大小限制,单位:bytes。

·maxRequestSize·:显示请求中数据的大小,单位:bytes。

@MultipartConfig(maxFileSize = 80000, maxRequestSize = 140000)

三、文件的下载

3.1、代码

package com.servlet; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Xiao_Lin * @date 2021/1/21 10:58 */ @WebServlet(urlPatterns = "/download") public class DownloadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取用户需要下载的文件名称 String fileName = req.getParameter("fileName"); // 获取文件所在的根路径 String realPath = req.getServletContext().getRealPath("/WEB-INF/upload/"); // 使用工具类Files的copy方法获取一个文件输出流,响应给浏览器 Files.copy(Paths.get(realPath,fileName),resp.getOutputStream()); } }

3.2、下载文件的名称问题

默认情况下,Tomcat 服务器未告知浏览器文件的名称,所以需要手动设置响应头来告知浏览器文件名

称。

// 给浏览器一个推荐名称 resp.setHeader("Content-Disposition", "attachment;filename=文件名称");

如果文件中有中文的话还涉及到需要处理中文乱码的问题,这里分为两个流派:

IE 使用 URL 编码方式:URLEncoder.encode(fileName, “UTF-8”)

非 IE使用 ISO-8859-1 编码:new String (fileName.getBytes(“UTF-8”), “ISO-8859-1”)

package com.servlet; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author Xiao_Lin * @date 2021/1/21 10:58 */ @WebServlet(urlPatterns = "/download") public class DownloadServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取用户需要下载的文件名称 String fileName = req.getParameter("fileName"); // 获取浏览器的类型 String header = req.getHeader("User-Agent"); // 如果包含MSIE说明是微软的浏览器(非IE),否则就不是IE String name = header.contains("MSIE") ? URLEncoder.encode(fileName, StandardCharsets.UTF_8) : new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1); // 设置文件的下载名 resp.setHeader("Content-Disposition","attachment;filename=" + name); // 获取文件所在的根路径 String realPath = req.getServletContext().getRealPath("/WEB-INF/upload/"); // 使用工具类Files的copy方法获取一个文件输出流,响应给浏览器 Files.copy(Paths.get(realPath,fileName),resp.getOutputStream()); } }

Servlet

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:JVM(和Spark)性能优化:使用Java Mission Control (1)
下一篇:年终盘点| 带你回顾2020华为云数据库这一年
相关文章