FileUpload系列:(1)文件上传的思路和示例

文件上传:第(1)阶段,处理流程

1、浏览器的表单上传文件到Tomcat服务器时,表单中的数据(包括普通文本域,也包括文件)被封装成了request对象
2、要想保存这些表单数据(普通文本、文件),就必须把这些信息从request对象抽取出来
3、把这些表单数据抽取出来的一个类叫做ServletFileUpload。
4、ServletFileUpload有一个方法parseRequest(HttpServletRequest)(A list of FileItem instances parsed from the request)能够从request对象中抽取信息,该方法的返回值是List<FileItem>。
5、那么什么是FileItem呢?它代表了multipart/form-data POST request中的一个file 或者是一个 form item。
6、接下来,对每个FileItem进行处理,或者读取普通文本域,或者读取文件内容。

文件上传:第(2)阶段,构造ServletFileUpload

1、在第一阶段当中,得出这样的结论:通过ServletFileUpload的parseRequest(HttpServletRequest)方法,可以得到一系列的FileItem。
2、在执行parseRequest(HttpServletRequest)方法之前,需要先构造ServletFileUpload对象。
3、ServletFileUpload有一个构造方法ServletFileUpload(FileItemFactory fileItemFactory),它接受一个FileItemFactory类型的对象。
4、FileItemFactory是一个接口,它的作用是创建FileItem对象实例。
5、小结:ServletFileUpload的parseRequest(HttpServletRequest)方法得到List<FileItem>对象,但是FileItem的创建实际上是由FileItemFactory对象创建的。
6、FileItemFactory是一个接口,它一个默认实现类是DiskFileItemFactory类。

文件上传:第(3)阶段,初识FileItem

1、通过ServletFileUpload的parseRequest(HttpServletRequest)方法,可以得到一系列的FileItem。
2、那么应该如何处理FileItem呢?如何区分它是一个普通的表单项,还是一个文件呢?如果是文件,该如何保存呢?
3、区分FileItem是“普通表单项,还是文件?”的方法是isFormField()。如果是普通表单项,则返回ture,如果是上传的文件,则返回false。
4、对于普通表单项,要获取它的表单项的name和value,用到的方法分别是getFieldName()和getString(String encoding)。
5、对于文件,要获取它的表单项的name(field name)、文件的名称(file name)和实际上传的文件,最终是要将文件保存到磁盘上。获取表单项name(field name)的方法是getFieldName(),获取文件的名称(file name)用getName(),获取文件的输入流用getInputStream()方法。

涉及到的方法:

----------通用方法

a)判断是普通表单项,还是文件?

boolean isFormField()

Determines whether or not a FileItem instance represents a simple form field.

Returns: true if the instance represents a simple form field; false if it represents an uploaded file.

b)获取表单项的名字(包括普通表单项和文件)

String getFieldName()

Returns the name of the field in the multipart form corresponding to this file item.

----------处理普通表单项方法

a)获取普通表单项的内容

String getString(String encoding)

Returns the contents of the file item as a String, using the specified encoding.

----------处理文件方法

a)得到文件的名字

String getName()

Returns the original filename

b)获取文件的输入流

InputStream getInputStream()

Returns an InputStream that can be used to retrieve the contents of the file.

文件上传:第(4)阶段,深入FileItem

1、处理【普通表单项】时,获取表单值用getString(String encoding),需要指定字符集(例如UTF-8)
        getString(String encoding),是需要开发人员指定字符集
        String getString(),使用“默认”的字符集
        这两个方法都是建立在byte[] get()方法之上的。
        如何查看“默认”的字符集呢?可以通过Charset.defaultCharset()查看。
2、处理【文件】时,如何确定是否上传文件?可以通过getSize()方法,如果返回的值为0,则表示没有上传文件。
3、处理【文件】时,可以通过getContentType()获取上传文件的一些类型信息,但是如果想判断上传的文件到底是什么类型,还是通过getName()得到文件名后,再截取文件名后缀得到。
4、处理【文件】时,生成的临时文件,如果比较小,则存储在内存当中;如果比较大,则存储在磁盘上。那么到底存储在什么位置呢?可以通过isInMemory()来进行判断。判断当前文件是大,还是小的域值,是在DiskFileItemFactory的构造方法中指定。isInMemory()和getSize()方法配合使用。
5、在进行保存【文件】时,可以使用IOUtils.copy(InputStream input, OutputStream output)的方法进行存储。也可以通过write(File file)写入到指定文件中。
6、在处理【文件】时,FileItem还提供了一个delete()方法,这个方法可以尽早的删除临时文件、释放系统资源。

涉及到的方法:

----------通用方法

a)得到普通表单项的值或者是文件的大小

long getSize()

Returns the size of the file item.

----------处理普通表单项方法

a)得到普通表单项的值,使用默认字符集

String getString()

Returns the contents of the file item as a String, using the default character encoding. This method uses get() to retrieve the contents of the item.

b)获取普通表单项的值的字节表示形式

byte[] get()

Returns the contents of the file item as an array of bytes.

----------处理文件方法

a)得到文件的类型

String getContentType()

Returns the content type passed by the browser or null if not defined.

文件:

.txt-->text/plain

.rar-->application/octet-stream

.html-->text/html

.jpg-->image/jpeg

.gif-->image/gif

.png-->image/png

b)是否位于内存当中isInMemory(),应该和getSize()配合使用吧

boolean isInMemory()

Provides a hint as to whether or not the file contents will be read from memory.

c)写入到文件

void write(File file)

A convenience method to write an uploaded item to disk. The client code is not concerned with whether or not the item is stored in memory, or on disk in a temporary location. They just want to write the uploaded item to a file.

d)删除临时文件

void delete()

Deletes the underlying storage for a file item, including deleting any associated temporary disk file. Although this storage will be deleted automatically when the FileItem instance is garbage collected, this method can be used to ensure that this is done at an earlier time, thus preserving system resources.

文件上传:第(5)阶段,深入ServletFileUpload

1、如果要限制单个上传文件的大小,可以使用setFileSizeMax(long fileSizeMax)
2、限制上传文件的总大小,可以使用setSizeMax(long sizeMax)
3、setHeaderEncoding(String encoding)方法可以指定读取请求头的编码,它对于getFieldName()和getName()方法有效,但对于getString()方法无效,因为getString()总是使用默认的字符集进行编码,因此要使用getString(String encoding)来代替getString()方法。

a)设置上传单个文件的大小

setFileSizeMax(long fileSizeMax)

Sets the maximum allowed size of a single uploaded file

b)设置上传文件的总大小

setSizeMax(long sizeMax)

Sets the maximum allowed size of a complete request, as opposed to setFileSizeMax(long).

c)设置编码

setHeaderEncoding(String encoding)

Specifies the character encoding to be used when reading the headers of individual part. When not specified, or null, the request encoding is used. If that is also not specified, or null, the platform default encoding is used.

文件上传:第(6)阶段,总结

1、第(1)阶段,讲处理的流程,由request-->ServletFileUpload-->FileItem
2、第(2)阶段,讲如何构造ServletFileUpload对象
3、第(3)阶段,对FileItem进行一个初步了解,就可以实现普通表单项和文件的读取和保存了。
4、第(4)阶段,对FileItem进一步深入,更详细的解释几个API方法
5、第(5)阶段,对ServletFileUpload的限制文件大小和字符编码做了介绍
6、由(1)至(5)阶段,都是对mutipart/form-data的post类型的表单进行处理。那么如何判断一个表单是普通表单,还是带有文件上传功能的表单呢?ServletFileUpload提供了一个静态方法isMultipartContent(HttpServletRequest request),用于判断当前表单是否为multipart/form-data的post类型的表单。

boolean isMultipartContent(HttpServletRequest request)

Utility method that determines whether the request contains multipart content.

文件上传示例

1、引入jar包

2、写jsp,用于在浏览器端选择上传文件

3、写servlet,用于在服务器处理上传文件的表单

1、引入jar包

commons-fileupload-1.3.1.jar
commons-io-2.4.jar

2、test.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE 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>上传文件示例</title>
</head>
<body>
	<form action="${pageContext.request.contextPath }/file" method="post" enctype="multipart/form-data">
		图书名称:<input type="text" name="bookname"/><br/>
		作者名称:<input type="text" name="username"/><br/>
		图书封面:<input type="file" name="bookcover"/><br/>
		<input type="submit" value="提交"/>
	</form>
</body>
</html>

3、FileServlet.java

package com.rk.web.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;

public class FileServlet extends HttpServlet
{
	private static final long serialVersionUID = -6986341005030926195L;

	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		FileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload fileUpload = new ServletFileUpload(factory);
		fileUpload.setFileSizeMax(1024 * 1024 * 5);//设置单个上传文件的大小
		fileUpload.setHeaderEncoding("UTF-8");//设置字符编码
		try
		{
			List<FileItem> listOfFilItem = fileUpload.parseRequest(request);
			for(FileItem fileItem : listOfFilItem)
			{
				if(fileItem.isFormField())
				{
					String fieldName = fileItem.getFieldName();
					String fieldValue = fileItem.getString("UTF-8");
					System.out.println(fieldName + "=" + fieldValue);
				}
				else
				{
					/*上传文件的大小*/
					long size = fileItem.getSize();
					if(size == 0)
					{
						System.out.println("当前没有上传文件!");
						continue;
					}
					else
					{
						System.out.println("当前上传文件的大小为:" + size + "字节");
					}

					/*上传文件的ContentType*/
					String contentType = fileItem.getContentType();
					System.out.println("当前上传文件的ContentType为:" + contentType);

					/*form field name*/
					String fieldName = fileItem.getFieldName();
					System.out.println("当前上传文件的form field name为:" + fieldName);

					/*上传文件的名字*/
					String fileName = fileItem.getName();
					String fileExtention =  fileName.substring(fileName.lastIndexOf("."));
					System.out.println("当前上传文件的名称为:" + fileName + ",它的扩展名为:" + fileExtention);

					/*将文件保存至磁盘*/
					//a)获取InputStream
					InputStream inputStream = fileItem.getInputStream();
					//b)获取OutputStream
					String path = this.getServletContext().getRealPath("/upload"); //保存的目标文件夹
					File file = new File(path,fileName);
					OutputStream outputStream = new FileOutputStream(file);
					//c)使用IOUtils进行拷贝
					IOUtils.copy(inputStream, outputStream);
					//d)关闭OutputStream
					outputStream.close();
				}
			}
		}
		catch (FileUploadException e)
		{
			e.printStackTrace();
		}
	}
	private String getUUID()
	{
		return UUID.randomUUID().toString().replaceAll("-", "");
	}
}
时间: 2024-10-13 12:25:41

FileUpload系列:(1)文件上传的思路和示例的相关文章

使用Commons FileUpLoad组件实现文件上传功能

Commons 是Apache开放的源码组织的一个java子项目,该项目主要涉及一些开发中常用的模块,如文件上传,命令行处理,数据库连接池等.FileUpLoad就是其中的一个用于处理HTTP文件上传的子项目.Commons FileUpLoad组建具有以下几个特点: 1.使用简单:Commons FileUpLoad组件可以方便的嵌入JSP文件中,在JSP文件中仅编写少量代码就可完成文件上传功能,十分方便. 2.能够全程控制上传的内容:使用Commons FileUpLoad组件提供的对象及操

JS组件系列——Bootstrap文件上传组件:bootstrap fileinput

原文:JS组件系列--Bootstrap文件上传组件:bootstrap fileinput 前言:之前的三篇介绍了下bootstrap table的一些常见用法,发现博主对这种扁平化的风格有点着迷了.前两天做一个excel导入的功能,前端使用原始的input type='file'这种标签,效果不忍直视,于是博主下定决心要找一个好看的上传组件换掉它.既然bootstrap开源,那么社区肯定有很多关于它的组件,肯定也有这种常见的上传组件吧.经过一番查找,功夫不负有心人,还是被博主找到了这个组件:

dwz+jquery+fileupload+springmvc实现文件上传 及图片预览

1 前台jsp:文件的上传利用了iframe实现局部刷新功能.使用了apache的fileupload组件,用到的jar: commons-fileupload.jar,commons-io.jarDiskFileItemFactory fac = new DiskFileItemFactory();ServletFileUpload upload = new ServletFileUpload(fac);upload.setHeaderEncoding("utf-8"); Html代

Oracle Apex 实用笔记系列 2 - 文件上传管理

1. 页面设计 页面A有若干region, 其中一个region用于文件列表管理(包括显示,下载,删除),如图A.在页面A有一button,点击它会调用页面B,页面B负责文件上传,如图B. 图A 图B 2. 数据库表设计 File FILE_ID           Number, FILE_DESC    Varchar2(256), CONTENT  Blob, mime_type varchar2(256), char_set     varchar2(256), last_update

Oracle Apex 有用笔记系列 2 - 文件上传管理

1. 页面设计 页面A有若干region, 当中一个region用于文件列表管理(包含显示,下载.删除).如图A. 在页面A有一button,点击它会调用页面B,页面B负责文件上传.如图B. 图A 图B 2. 数据库表设计 File FILE_ID           Number, FILE_DESC    Varchar2(256), CONTENT  Blob, mime_type varchar2(256), char_set     varchar2(256), last_update

form表单系列中文件上传及预览

文件上传及预览 Form提交 Ajax 上传文件 时机: 如果发送的[文件]:->iframe, jQurey(),伪Ajax 预览 import os img_path = os.path.join('static/img', fafafa.name) with open(img.path, 'wb') as f: for item in fafafa.chunks(): f.write(item) function iframeSubmit(){ $('#ifm1').load(functi

[转]ExtJs入门之filefield:文件上传的配置+结合Ajax完美实现文件上传的asp.net示例

原文地址:http://www.stepday.com/topic/?459 作文一个ExtJs的入门汉子,学习起来的确是比较费劲的事情,不过如今在这样一个网络资源如此丰富的时代,依然不是那么难了的.基本上都是Copy过来加以部分改造即可实现自己想要的功能,加之如今的第三方开发者也大发慈悲地写出了API的帮助文档以及示例文档.关于ExtJs内的文件上传,将从以下几个方面进行展开讲解: 一.ExtJs文件上传版面的布局以及配置 因为ExtJs的文件上传组件filefield是基于form表单提交数

文件上传的几个 - 示例

本篇将要和朋友们分享的是几个上传文件的例子和逻辑步奏及自定义个简单的js上传插件我取名为shenniu.upfile-0.0.1.js:近来在讨论组中很有几个朋友咨询上传文件的代码和怎么下载上传的文件,所以写了此篇文章,希望能为朋友们解答一些疑惑或能带来帮助,也谢谢各位多多支持点赞. 以上是个人的看法,下面来正式分享今天的文章吧: . 使用iis发布保存上传文件的文件夹 . 示例A - 普通表单上传文件,Request.Files获取上传文件 . 示例B - 普通表单上传文件,HttpPoste

Rop 文件上传解决思路

由于服务请求报文是一个文本,无法直接传送二进制的文件内容,因此必须采用某种转换机制将二进制的文件内容转换为字符串.Rop 采用如下的方式对上传文件进行编码:<fileType>@<BASE64( 文件内容 )><fileType>代表文件类型,文件内容采用 BASE64 算法进行编码,这样二进制的文件内容就可以转换为一个字符串,两者“@”字符分隔.服务端接收到上传的文件后,即可解析出文件的类型和文件的内容.Rop 定义了一个 UploadFile,代表一个上传的文件,来