如何实现网站中文件的上传?——Javaweb

文件上传

一、对表单的一些要求

  1. 提交方法必须是post:method="post"
  2. 编码属性必须是multipart/form-data,也就是“多组件的表单数据”,即enctype="multipart/form-data"
    在这里插入图片描述
  3. 表单中需要添加文件表单项,即<input type="file" name="xxx" />

示例:

<body>
	<h1>上传1</h1>
	<form action="<c:url value='/Upload1Servlet'/>" method="post" enctype="multipart/form-data">
		用户名:<input type="text" name="username" /><br>
		照片:<input type="file" name="zhaopian" /><br>
		<input type="submit" value="上传" />
	</form>
</body>

在这里插入图片描述

二、对servlet的一些要求

我们回忆一下我们以前用来接收表单传递过来的参数,使用的request.getParameter("xxx"),而这个方法在表单为enctype="multipart/form-data"时,就作废了。它永远都会返回null。
那么我们应该使用什么样的方法呢?是request.getInputStream(),返回值为ServletInputStream类型,它会包含整个请求的体。

接下来我们研究一下多部件表单的体。

三、多部件表单请求体

  1. 分隔出多个部件,即一个表单项一个部件。
  2. 一个部件中自己包含请求头和空行,以及请求体。
  3. 普通表单项:
    只有一个头:Content-Disposition:包含name=“xxxx”,即表单项名称。
    体就是表单项的值
  4. 文件表单项:
    有两个头:
    Content-Disposition:包含name="xxxx",即表单项名称;还有一个filename="xxx",表示上传文件的名称
    Content-Type:它是上传文件的MIME类型,例如:image/pjpeg,表示上传的是图片,其中是jpg扩展名的图片。
    体就是上传文件的内容

四、使用servlet获取表单上传的数据

我们写一个相应的Servlet:

public class Upload1Servlet extends HttpServlet {
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");

		ServletInputStream in = request.getInputStream();
		String s = IOUtils.toString(in);
		System.out.println(s);	
	}
}

然后我们在页面表单上输入一些内容,然后在后台查看会输出什么。
在这里插入图片描述
后台内容:
在这里插入图片描述
我们可以清楚的看到上传组件的部分构成。

五、commons-fileupload组件介绍

我们在上面的示例中获取了表单上传的数据,但是明显的是,我们上传的是一张图片,后台显示出来的是一堆字符乱码,这显然是没用的,我们就要想办法把它变成图片,这个时候应该怎么做呢?

我们通过观察,可以发现,请求体是有一定的固定格式的,我们很容易联想到我们采取字符串分割一步步得到我们想要的内容,但是这样有点太过于麻烦,这个时候我们应该怎么办呢?其实Apache已经帮我们提供了解析它的工具:commons-fileupload

fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()

fileupload组件需要的JAR包有:
- commons-fileupload.jar,核心包;
- commons-io.jar,依赖包。

这个小组件,它会帮我们解析request中的上传数据,解析后的结果是一个表单项数据封装到一个FileItem对象中。我们只需要调用FileItem的方法即可!

fileupload的核心类有:DiskFileItemFactoryServletFileUploadFileItem
使用fileupload组件的步骤如下:
1). 创建工厂类DiskFileItemFactory对象:DiskFileItemFactory factory = new DiskFileItemFactory();
2). 使用工厂创建解析器对象:ServletFileUpload fileUpload = new ServletFileUpload(factory);
3). 使用解析器来解析request对象:List<FileItem> list = fileUpload.parseRequest(request);

我们重点介绍一下FileItem类。一个FileItem对象对应一个表单项(表单字段)。一个表单中存在文件字段和普通字段,可以使用FileItem类的isFormField()方法来判断表单字段是否为普通字段,如果不是普通字段,那么就是文件字段了。

  • String getName():获取文件字段的文件名称;
  • String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
  • String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username;
  • String getContentType():获取上传的文件的类型,例如:text/plain。
  • int getSize():获取上传文件的大小;
  • boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
  • InputStream getInputStream():获取上传文件对应的输入流;
  • void write(File):把上传的文件保存到指定文件中。

六、上传的实例

接下来我们写一下上传的示例。

首先新建一个jsp,放入一个表单:

<body>
	<h1>上传2</h1>
	<form action="<c:url value='/Upload2Servlet'/>" method="post" enctype="multipart/form-data">
		用户名:<input type="text" name="username" /><br>
		照片:<input type="file" name="zhaopian" /><br>
		<input type="submit" value="上传" />
	</form>
</body>

接下来是我们的servlet:

public class Upload2Servlet extends HttpServlet {

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");

		/*
		 * 上传的三步: 
		 * 1.创建工厂类; 
		 * 2.通过工厂类创建解析器; 
		 * 3.解析request,得到FileItem集合
		 * 4.遍历FileItem集合,调用其API完成文件的保存
		 */
		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload sfu = new ServletFileUpload(factory);
		try {
			List<FileItem> fileItemList = sfu.parseRequest(request);
			FileItem fi1 = fileItemList.get(0);
			FileItem fi2 = fileItemList.get(1);

			System.out.println("普通表单项演示:" + fi1.getFieldName() + "="
					+ fi1.getString("UTF-8"));

			System.out.println("文件表单项演示:");
			System.out.println("Content-Type:" + fi2.getContentType());
			System.out.println("size:" + fi2.getSize());
			System.out.println("filename:" + fi2.getName());

			// 保存文件
			File destFile = new File("E:/test.jpg");
			fi2.write(destFile);
			
		} catch (FileUploadException e) {
			throw new RuntimeException(e);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

我们在浏览器中打开网页,并且选择一张图片:
在这里插入图片描述
我们看一下后台出现了什么:
在这里插入图片描述
我们再看一下我们的E盘下有没有出现一个新的文件:
在这里插入图片描述
我们发现,功能全部符合我们的预期。


下一步,我们就要研究一下文件上传中的一些其他的细节问题。


END.

发布了166 篇原创文章 · 获赞 55 · 访问量 8万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章