前端文件上传
这里说的文件上传和文件下载都是针对客户端进行的操作
-
使用如下jsp代码,通过Servlet获取表单数据,是否可以获取到文件信息
<%-- Created by IntelliJ IDEA. User: carl Date: 2021/10/9 Time: 15:46 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>文件上传</title> </head> <body> <form method="post" action="http://127.0.0.7:8080/JavaWeb/myServlet"> <input type="text" name="username"/><br/> <input type="file" name="upload"/><br/> <input type="submit" name="提交"/> </form> </body> </html>
package com.carl.controller; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author :Carl_蔡先生 * @version :JDK1.8 * @description:TODO * @date :2021/10/8 16:06 * @month_name :10月 * @week : */ public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("我是get"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String upload = req.getParameter("upload"); System.out.println(upload); } }
-
配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <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>MyServlet</servlet-name> <servlet-class>com.carl.controller.UploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/myServlet</url-pattern> </servlet-mapping> <listener> <listener-class>com.carl.listener.MyListener</listener-class> </listener> </web-app>
很明显:当我们使用Servlet获取name=upload的内容时,获取的只是文件名,通过浏览器我们不难发现,上传的只是一个文件名
后端获取前端上传文件流
-
实现真正的文件上传
在form表单属性中加上enctype="multipart/form-data"
multipart/form-data:表示提交的数据,会以多段的形式进行拼接,然后以二进制流的形式发送给服务器
-
如何证实是以流的形式将数据请求发送到服务器了
首先:我们添加了multipart/form-data后,无法再使用request.getParameter这个方法获取到任何信息,因为传输的方式变了
其次:浏览器以流的形式发送请求,势必服务器也要用流的方式进行接收protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); ServletInputStream inputStream = req.getInputStream(); byte[] b=new byte[1024]; int len = inputStream.read(b); System.out.println(new String(b,0,len)); } ------WebKitFormBoundaryidn5jp863QXWwCps Content-Disposition: form-data; name="username" [email protected] ------WebKitFormBoundaryidn5jp863QXWwCps Content-Disposition: form-data; name="upload"; filename="DSC08260.jpg" Content-Type: image/jpeg
解析:
上图所示是请求体
上图的内容是二进制文件的内容
获取文件上传信息
-
导入jar包–fileupload包依赖于io的jar包
-
常用的类和方法
ServletFileUpload类:用于解析上传数据 常用方法: boolean mc = ServletFileUpload.isMultipartContent(req);判断当前请求数据是否是以多段的流形式进行传输的 List<FileItem> list = servletFileUpload.parseRequest(req);用于解析上传的数据 ServletFileUpload servletFileUpload = new ServletFileUpload(fif);构造器:内部要传输一个FileItemFactory对象,而FileItemFactory是一个接口,子类中只有DiskFileItemFactory实现类,另一个已经过时了,因此,创建的该FileItemFactory需要使用多态的方式FileItemFactory fif=new DiskFileItemFactory(); FileItem类:表示每一个表单项 常用方法: boolean isFormField():判断当前这个表单项是否是普通的表单项,true则表示是普通类型的表单项,false表示上传的文件类型 String getFieldName():获取表单项的name属性值 String getString():获取当前表单项的值value String getName():获取上传文件的文件名 void write(file):将上传的文件写入到参数file所指向的硬盘位置
req.setCharacterEncoding("UTF-8"); boolean mc = ServletFileUpload.isMultipartContent(req); System.out.println(mc);//true if (mc) { FileItemFactory fif=new DiskFileItemFactory(); ServletFileUpload servletFileUpload = new ServletFileUpload(fif); List<FileItem> list = null; try { list = servletFileUpload.parseRequest(req); for (FileItem fileItem : list) { if (fileItem.isFormField()) { System.out.println("表单项的name属性值:"+fileItem.getFieldName()); System.out.println("表单项的value属性值"+fileItem.getString("UTF-8")); }else{ System.out.println("表单项的name属性值:"+fileItem.getFieldName()); System.out.println("表单项的value属性值:"+fileItem.getName()); fileItem.write(new File("E:\\a.jpg")); } } } catch (Exception e) { e.printStackTrace(); } }
文件下载
response.getOutputStream();
servletContext.getResourceAsStream();
servletContext.getMimeType();
response.setContextType();
文件下载一:从服务器获取图片供客户端下载
预先,需要编写一个Servlet用于下载,如果是直接访问,则最好设置为get请求,网页链接的方式都是GET请求
配置web.xml
-
获取需要下载的文件在浏览器中的数据类型(MIME)
首先获取文件的类型,需要使用ServletContext域对象中的getMimeType()方法ServletContext servletContext = getServletContext();
String downloadFileName="a.jpg"; String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
resp.setContentType(mimeType);
第四步:告诉浏览器,我这个文件是用来干什么的;Content-Disposition是MIME协议的扩展,是一个响应头
Content-Disposition是一个指示浏览器响应的内容应该以何种形式进行展示
有两种方式:内联和附件;
-
内联是将响应内容作为网页的一部分进行展示;
-
附件是将响应的内容支持下载的形式保存到本地;详细描述可参考该地址
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("中国.jpg", "UTF-8"));
-
-
获取输入流:将该文件从服务器本地获取输入流,输入到ServletContext对象中
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
-
获取输出流:获取Response对象的输出流–因为需要Response将文件通过流的方式输出给浏览器
ServletOutputStream outputStream = resp.getOutputStream();
-
将输入流的文件信息copy给输出流:将ServletContext对象中的输入流获取的文件信息,复制到输出流中,通过输出流反馈给浏览器
int copy = IOUtils.copy(resourceAsStream, outputStream);
文件下载二:从客户端发送下载请求,提交给服务器进行下载
我们可以根据用户上传的图片,下载到服务器本地,再通过请求重定向的方式,进行下载–请求重定向就必须将被重定向的Servlet设置为Get请求
package com.carl.controller;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* @author :Carl_蔡先生
* @version :JDK1.8
* @description:TODO
* @date :2021/10/8 16:06
* @month_name :10月
* @week :
*/
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
req.setCharacterEncoding("UTF-8");
boolean mc = ServletFileUpload.isMultipartContent(req);
System.out.println(mc);//true
if (mc) {
FileItemFactory fif=new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(fif);
List<FileItem> list = null;
try {
list = servletFileUpload.parseRequest(req);
for (FileItem fileItem : list) {
if (fileItem.isFormField()) {
System.out.println("表单项的name属性值:"+fileItem.getFieldName());
System.out.println("表单项的value属性值"+fileItem.getString("UTF-8"));
}else{
System.out.println("表单项的name属性值:"+fileItem.getFieldName());
System.out.println("表单项的value属性值:"+fileItem.getName());
fileItem.write(new File("E:\\文档\\Java_WorkSpace\\JavaWeb\\web\\file\\a.jpg"));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
resp.sendRedirect("downloadServlet");
}
}
package com.carl.controller;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.chrono.MinguoEra;
import java.util.List;
/**
* @author :Carl_蔡先生
* @version :JDK1.8
* @description:TODO
* @date :2021/10/9 19:42
* @month_name :10月
* @week :
*/
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取Servlet上下文对象
ServletContext servletContext = getServletContext();
String downloadFileName="a.jpg";
//通过Servlet上下文获取/file/a.jpg文件的类型
String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
//将该类型传递给响应对象
resp.setContentType(mimeType);
//设置响应头Content-Disposition:attachment;filename,这是为了告诉浏览器attachment是一个附件,一个需要下载的文件,file后面跟随的就是需要下载的文件名
//URLEncoder.encode()标记UTF-8编码,告诉浏览器该文件名按UTF-8进行解析,但是不同浏览器可能不同,最好是用Base64编解码操作
resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("中国.jpg", "UTF-8"));
//获取请求的输入流
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
//获取响应的输出流
ServletOutputStream outputStream = resp.getOutputStream();
int copy = IOUtils.copy(resourceAsStream, outputStream);
}
}
标签:文件,上传下载,req,System,println,import,servlet,fileItem
From: https://blog.csdn.net/qq_39052339/article/details/139660418