JSP中的文件上传

文件上传

准备:
1):上传控件所在的表单的method,必须是POST:
因为GET方式传入的数据大小不能超过2KB,而PSOT没有大小限制。

<form method="POST">

2):上传控件得使用type为file的类型

<input type="file" name="headImg" />

3) :表单的编码方式必须时二进制编码

<form enctype="multipart/form-data">

在API文档中找form标签下的enctype属性:
在这里插入图片描述


初步文件代码:
upload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h3>文件上传</h3><br/>
	<form action="/upload-download-i18n/upload" method="POST" enctype="multipart/form-data">
		账号:<input type="text" name="username"/><br/>
		邮箱:<input type="text" name="email"/><br/>
		头像:<input type="file" name="headImg" accept="image/*"/><br/>
		<input type="submit" value="朕要提交"/><br/>
	</form>
</body>
</html>

uploadServlet.java

@WebServlet("/upload")
public class UploadServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		System.out.println(req.getParameter("username"));
		System.out.println(req.getParameter("email"));
		System.out.println(req.getParameter("headImg"));
	}
}

不同编码区别:

application/x-www-form-urlencoded(默认)编码:
*
*
网页输入数据并提交
在这里插入图片描述
eclipse中显示内容:
在这里插入图片描述
注意:这里显示的文件名称仅仅就是文件名称,没有内容。
在这里插入图片描述


multipart/form-data编码:
*
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
用此编码使每个参数分成了单独一块,其中文件、图片等直接将内容转码后上传不再仅仅传入一个文件名称。
但是这时候就不能在Servlet中使用request .setParameter(“key”);来获取对应的参数值。




解决multipart/form-data编码无法传参问题:
使用FileUpload组件
1):引入jar包
common-fileupload-xxxx.jar 下载
common-io-xxx.jar 下载
2):将上述的uploadServlet.java改为:

@WebServlet("/upload")
public class UploadServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//解析和检查请求:请求方式是否是POST,请求编码是否是muitipart/form-data
		boolean isMultipart = ServletFileUpload.isMultipartContent(req);
		if(!isMultipart) {
			return;
		}
		try {
			//1.创建FileItemFactory对象
			//FileItemFactory是用来创建FileItem对象的
			//FileItem对象:form表单中的表单控件的封装
			FileItemFactory factory = new DiskFileItemFactory();
			//2.创建文件上传处理器
			ServletFileUpload upload = new ServletFileUpload(factory);
			//3.解析请求
			List<FileItem> items = upload.parseRequest(req);
			//4.迭代出每一个FileItem
			for(FileItem item : items) {
				String fieldName = item.getFieldName();//获取表单控件的name属性值(参数名)
				if(item.isFormField()) {
					//普通表单控件
					String value = item.getString("UTF-8");
					System.out.println(fieldName + "-" + value);
				}else {
					//表单上传控件
					System.out.println(fieldName + "-" + item.getName());
					item.write(new File("E:/JAVA/FileUpload/", item.getName()));//把二进制数据写到哪一个文件中
				}
			}
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

注解:
1.先进行判断在upload.jsp中的请求方式是否为:POST,编码格式是否为:multipart/form-data
有一种不对相应就直接结束程序

if(!isMultipart) {
			return;
		}

2.创建一个FileItem工厂对象(FileItemFactory),再在工厂对象中创建文件上传处理器(ServletFileUpload)

	FileItemFactory factory = new DiskFileItemFactory();
	ServletFileUpload upload = new ServletFileUpload(factory);

3.使用List集合将响应中的所用FileItem存入集合中

List<FileItem> items = upload.parseRequest(req);

4.迭代出每一个FileItem对象

for(FileItem item : items) 

5.判断每一个控件是普通控件还是上传控件

if(item.isFormField()) 

6.普通控件 ------ 读取参数值(如果参数值有汉字,需要使用UTF-8编码)

//普通表单控件
					String value = item.getString("UTF-8");
					System.out.println(fieldName + "-" + value);

7.上传控件-------读取参数值(方法参数为:目标路径 和 文件名称)

//表单上传控件
					System.out.println(fieldName + "-" + item.getName());
					item.write(new File("E:/JAVA/FileUpload/", item.getName()));//把二进制数据写到哪一个文件中

上传文件的名称问题

1):文件名处理
IE6问题:通过FileItem.getName方法获取上传文件的名称,此时会带有路径:
其他浏览器:c.png
IE6:c:/a/b/c.png
解决方案:
使用FilenameUtils.getName(path)
上传文件名称重复问题
给上传的文件起唯一的名称:使用UUID产生随机数,再加文件名
String fileName = UUID.randomUUID().toString()+"."+FilenameUtils.getExtension(item.getName());
**上传文件的保存路径:**一般的,把上传文件保存到应用里面
2):缓存大小和临时目录:
超过多少就不直接存放在内存中了(缓存大小):默认值是10KB.
在DiskFileItemFactory类中有:
在这里插入图片描述
不存在内存,放在临时目录中:默认Tomcat根/temp目录。 不建议修改。
在这里插入图片描述
注:判断文件是否在内存中方法
item.isInMemory();
3):文件类型约束:
方法一:
在这里插入图片描述
若判断是上传文件时,判断上传文件类型是否符合要求:
在这里插入图片描述
如果上传文件类型符合要求,则继续上传,否则返回错误信息到jsp文件中显示给用户
在这里插入图片描述
在这里插入图片描述
方法二:
判断上传文件的MIME类型:
String str = super.getServletContext().getMimeType(item.getName());
如:上传类型需要是图片就会以image开头,为:image/* 的格式,不同文件类型的MIME类型不同。



抽取文件上传工具方法:

自定义一个异常类(LogicException继承runtimeException)----接受文件类型异常

public class LogicException extends RuntimeException{
	private static final long serialVersionUID = 1L;

	public LogicException(String message, Throwable cause) {
		super(message, cause);
	}

	public LogicException(String message) {
		super(message);
	}

}

其中的构造方法可自动生成:
空白处右键---->Source---->Generate Constructors from Superclass
在这里插入图片描述
选择
LogicException(String , Throwable )
LogicException(String )
两项即可:

工具类—上传文件方法:

public class FileUtil {
	
	//允许接受上传的文件类型(如:图片)
	private static final String ALLOWED_IMAGE_TYPE="png;gif;jpg;jpeg";

	public static void upload(HttpServletRequest req){
		//解析和检查请求:请求方式是否是POST,请求编码是否是muitipart/form-data
		boolean isMultipart = ServletFileUpload.isMultipartContent(req);
		if(!isMultipart) {
			return;
		}
		try {
			//1.创建FileItemFactory对象
			//FileItemFactory是用来创建FileItem对象的
			//FileItem对象:form表单中的表单控件的封装
			DiskFileItemFactory factory = new DiskFileItemFactory();
			//2.创建文件上传处理器
			ServletFileUpload upload = new ServletFileUpload(factory);
			//3.解析请求
			List<FileItem> items = upload.parseRequest(req);
			//4.迭代出每一个FileItem
			for(FileItem item : items) {
				String fieldName = item.getFieldName();//获取表单控件的name属性值(参数名)
				if(item.isFormField()) {
					//普通表单控件
					String value = item.getString("UTF-8");
					System.out.println(fieldName + "-" + value);
				}else {
					//----------------------------------------------------------
					//上传文件的拓展名
					String ext = FilenameUtils.getExtension(item.getName());
					String[] allowedImageType = ALLOWED_IMAGE_TYPE.split(";");
					
					//当前上传类型不再允许的范围内
					if(!Arrays.asList(allowedImageType).contains(ext)) {
						throw new LogicException("上传格式错误,请重新上传");
						
					}
					//----------------------------------------------------------
					//表单上传控件
					System.out.println("上传文件的名称:"+item.getName());
					//文件名称
					String fileName = UUID.randomUUID().toString()+"."
									+FilenameUtils.getExtension(item.getName());
					//目标的绝对路径"E:/JAVA/My_eclipseEE/upload-download-i18n/webapp/upload"
					String dir = req.getServletContext().getRealPath("/upload");
					//把二进制数据写到哪一个文件中
					item.write(new File(dir, fileName));	
				}
			}
		}catch(LogicException e) {
			throw e;//继续抛出异常类给该类调用者(UploadServlet)
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

在工具类中定义上传文件类型、和上传方法;
在上传方法中判断是否符合文件类型,如果不符合就抛出LogicException异常,由于Exception接受所有异常并处理,使异常信息无法传到JSP文件显示给用户,所以在抛出Exception之前要先抛出LogicException异常,再在LogicException中抛出给调用者(UploadServlet)中处理。

UploadServlet.java(调用者)

@WebServlet("/upload")
public class UploadServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		try {
			FileUtil.upload(req);
		}catch(LogicException e) {
			String errorMsg = e.getMessage();//获取异常信息
			req.setAttribute("errorMsg",errorMsg);
			req.getRequestDispatcher("/upload.jsp").forward(req, resp);
		}
	}
}

直接调用工具类中的上传文件的方法upload;
返回的异常信息是:如果上传的文件格式不符,则返回在upload方法中自定义的错误信息,通过在catch中获取异常信息,并传给jsp文件显示错误信息,让用户重新进行上传。



上传文件大小约束:

情况1:单个文件超过指定的大小。 upload.setFileSizeMax(102410242);//2M
情况2:该次请求的全部数据超过指定的大小。upload.setSizeMax(102410243);//3M

在java文件中增加文件大小限制:
在这里插入图片描述
在这里插入图片描述
注意:
catch中抛出的异常类是自定义的异常类(LogicException源码同上)
在JSP文件中增加一个上传文件:
在这里插入图片描述
上传失败:
在这里插入图片描述
注:
如果设置过后运行不会出现错误信息提示,直接网页报错,说明自定义设置的限制文件大小大于系统页面规定的的组件大小,如果组件大小超过系统规定,应该单独去写该组件。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值