文件上传

使用文件上传功能,需要jar包支持:

commons-fileuplod.jar

commons-io.jar

1、在文件上传的表单中,要注明上传的特有类型:

enctype="multipart/form-data"

表单实例如下:

上传测试:<br>
<form method="post" enctype="multipart/form-data" action="./uploadTest/myUpload9">
请选择文件:<input type="file" name = "file1"/><br>
<input type = "text" name="username" value="fxt"/>
<input type = "password" name="password" value=""/>
<input type="submit" value="上传"/>
</form>
</body>

2、     在web.xml中配置servlet

<servlet>
<servlet-name>UploadTest</servlet-name>
<servlet-class>uploadTest.myUpload</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadTest</servlet-name>
<url-pattern>/uploadTest/myUpload9</url-pattern>
</servlet-mapping>

3、     在servlet中进行上传处理

//得到上传文件的保存目录(上传文件位于服务器项目下相应地址,而不是项目本身的地址)
	//(将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全)
	String savePath = this.getServletContext().getRealPath("/uploadFiles");
	File file = new File(savePath);
	//判断上传文件的保存目录是否存在
	if (!file.exists() && !file.isDirectory()) {
	//若不存在,创建目录
	file.mkdir();
	}
	//定义消息提示
	String message = "";
	try{
	//使用Apache文件上传组件处理文件上传步骤:
	//1、创建一个DiskFileItemFactory工厂
	DiskFileItemFactory factory = new DiskFileItemFactory();
	//2、创建一个文件上传解析器
	ServletFileUpload upload = new ServletFileUpload(factory);
	//解决上传文件名的中文乱码
	upload.setHeaderEncoding("UTF-8"); 
	//3、判断提交上来的数据是否是上传表单的数据(即类型是否是enctype="multipart/form-data")
	if(!ServletFileUpload.isMultipartContent(request)){
	//按照传统方式获取数据
	return;
	}
	//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
	List<FileItem> list = upload.parseRequest(request);
	for(FileItem item : list){
	//如果fileitem中封装的是普通输入项的数据
	if(item.isFormField()){
	//获得普通输入项的方法
	if("username".equals(item.getFieldName()){
//获得输入项的值(解决普通输入项的数据的中文乱码问题)
String username = item.getString("UTF-8");
}
	}else{
	//如果fileitem中封装的是上传文件
	//得到上传的文件名称,
	String filename = item.getName();
	if(filename==null || filename.trim().equals("")){
	continue;
	}
	//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
	//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
	filename = filename.substring(filename.lastIndexOf("\\")+1);
	//获取item中的上传文件的输入流
	InputStream in = item.getInputStream();
	//创建一个文件输出流
	FileOutputStream out = new FileOutputStream(savePath + "\\" + filename);
	//创建一个缓冲区
	byte buffer[] = new byte[1024];
	//判断输入流中的数据是否已经读完的标识
	int len = 0;
	//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
	while((len=in.read(buffer))>0){
	//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
	out.write(buffer, 0, len);
	}
	//关闭输入流
	in.close();
	//关闭输出流
	out.close();
	//删除处理文件上传时生成的临时文件
	item.delete();
	message = "文件上传成功!";
	}
	}
	}catch (Exception e) {
	message= "文件上传失败!";
	e.printStackTrace();
	}
	request.setAttribute("message",message);
	//将页面重定向到message页面
	request.getRequestDispatcher("/message.jsp").forward(request, response);
	}


上传常用类方法:


FileItem类的常用方法:

1. boolean isFormField()

       isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段则返回true,否则返回false。因此,可以使用该方法判断是否为普通表单域,还是文件上传表单域。

2. String getName()

      getName方法用于获得文件上传字段中的文件名。

       注意IEFireFox中获取的文件名是不一样的,IE中是绝对路径,FireFox中只是文件名。

3. String getFieldName()

     getFieldName方法用于返回表单标签name属性的值。如上例中<inputtype="text" name="column" />value

4. void write(File file)

       write方法用于将FileItem对象中保存的主体内容保存到某个指定的文件中。如果FileItem对象中的主体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除。该方法也可将普通表单字段内容写入到一个文件中,但它主要用途是将上传的文件内容保存在本地文件系统中。

5. String getString()

     getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回,它有两个重载的定义形式:

     public java.lang.String getString()

     public java.lang.String getString(java.lang.String encoding)

            throws java.io.UnsupportedEncodingException

       前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定的字符集编码将主体内容转换成字符串。如果在读取普通表单字段元素的内容时出现了中文乱码现象,请调用第二个getString方法,并为之传递正确的字符集编码名称。

6. String getContentType()

       getContentType 方法用于获得上传文件的类型,即表单字段元素描述头属性“Content-Type”的值,如“image/jpeg”。如果FileItem类对象对应的是普通表单字段,该方法将返回null

7. boolean isInMemory()

       isInMemory方法用来判断FileItem对象封装的数据内容是存储在内存中,还是存储在临时文件中,如果存储在内存中则返回true,否则返回false

8. void delete()

      delete方法用来清空FileItem类对象中存放的主体内容,如果主体内容被保存在临时文件中,delete方法将删除该临时文件。

       尽管当FileItem对象被垃圾收集器收集时会自动清除临时文件,但及时调用delete方法可以更早的清除临时文件,释放系统存储资源。另外,当系统出现异常时,仍有可能造成有的临时文件被永久保存在了硬盘中。

9. InputStream getInputStream()

    以流的形式返回上传文件的数据内容。

10. long getSize()

      返回该上传文件的大小(以字节为单位)。

 DiskFileItemFactory

将请求消息实体中的每一个项目封装成单独的DiskFileItem(FileItem接口的实现) 对象的任务

org.apache.commons.fileupload.FileItemFactory 接口的默认实现

org.apache.commons.fileupload.disk.DiskFileItemFactory来完成。当上传的文件项目比较小时,直接保存在内存中(速度比较快),比较大时,以临时文件的形式,保存在磁盘临时文件夹(虽然速度慢些,但是内存资源是有限的)。

属性

1) public static final intDEFAULT_SIZE_THRESHOLD :将文件保存在内存还是磁盘临时文件夹的默认临界值,值为10240,即10kb

2) private File repository:用于配置在创建文件项目时,当文件项目大于临界值时使用的临时文件夹,默认采用系统默认的临时文件路径,可以通过系统属性java.io.tmpdir获取。如下代码:

System.getProperty("java.io.tmpdir");

3) private int sizeThreshold:用于保存将文件保存在内存还是磁盘临时文件夹的临界值

构造方法

1) public DiskFileItemFactory()

      采用默认临界值和系统临时文件夹构造文件项工厂对象。

2) public DiskFileItemFactory(int sizeThreshold,Filerepository)

      采用参数指定临界值和系统临时文件夹构造文件项工厂对象。

3) FileItem createItem()

       根据DiskFileItemFactory相关配置将每一个请求消息实体项目创建成DiskFileItem实例,并返回。该方法从来不需要我们亲自调用,FileUpload组件在解析请求时内部使用。

4) void setSizeThreshold(int sizeThreshold)

       Apache文件上传组件在解析上传数据中的每个字段内容时,需要临时保存解析出的数据,以便在后面进行数据的进一步处理(保存在磁盘特定位置或插入数据库)。因为Java虚拟机默认可以使用的内存空间是有限的,超出限制时将会抛出“java.lang.OutOfMemoryError”错误。如果上传的文件很大,例如800M的文件,在内存中将无法临时保存该文件内容,Apache文件上传组件转而采用临时文件来保存这些数据;但如果上传的文件很小,例如600个字节的文件,显然将其直接保存在内存中性能会更加好些。

       setSizeThreshold方法用于设置是否将上传文件已临时文件的形式保存在磁盘的临界值(以字节为单位的int值),如果从没有调用该方法设置此临界值,将会采用系统默认值10KB。对应的getSizeThreshold()方法用来获取此临界值。

5) void setRepository(File repository)

       setRepositoryPath方法用于设置当上传文件尺寸大于setSizeThreshold方法设置的临界值时,将文件以临时文件形式保存在磁盘上的存放目录。有一个对应的获得临时文件夹的 FilegetRespository() 方法。

        注意:当从没有调用此方法设置临时文件存储目录时,默认采用系统默认的临时文件路径,可以通过系统属性java.io.tmpdir 获取。如下代码:

System.getProperty("java.io.tmpdir");

Tomcat系统默认临时目录为“<tomcat安装目录>/temp/”。

 ServletFileUpload

org.apache.commons.fileupload.servlet.ServletFileUpload类是Apache文件上传组件处理文件上传的核心高级类(所谓高级就是不需要管底层实现,暴露给用户的简单易用的接口)。

使用其parseRequest(HttpServletRequest) 方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回。使用该方法处理上传文件简单易用。

如果你希望进一步提高新能,你可以采用 getItemIterator 方法,直接获得每一个文件项的数据输入流,对数据做直接处理。

在使用ServletFileUpload对象解析请求时需要根据DiskFileItemFactory对象的属性sizeThreshold(临界值)和repository(临时目录)来决定将解析得到的数据保存在内存还是临时文件中,如果是临时文件,保存在哪个临时目录中?。所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性。

ServletFileUpload继承结构:

java.lang.Object

|—org.apache.commons.fileupload.FileUploadBase

    |—org.apache.commons.fileupload.FileUpload

|—org.apache.commons.fileupload.servlet.ServletFileUpload

构造方法:

1) public ServletFileUpload()

     构造一个未初始化的实例,需要在解析请求之前先调用setFileItemFactory()方法设置fileItemFactory属性。

2) public ServletFileUpload(FileItemFactoryfileItemFactory)

     构造一个实例,并根据参数指定的FileItemFactory对象,设置fileItemFactory属性。

ServletFileUpload类常用方法:

1) public void setSizeMax(long sizeMax)

       setSizeMax方法继承自FileUploadBase类,用于设置请求消息实体内容(即所有上传数据)的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。

       在请求解析的过程中,如果请求消息体内容的大小超过了setSizeMax方法的设置值,将会抛出FileUploadBase内部定义的SizeLimitExceededException异常(FileUploadException的子类)。该方法有一个对应的读方法:publiclong getSizeMax()方法。

2) public void setFileSizeMax(longfileSizeMax)

       setFileSizeMax方法继承自FileUploadBase类,用于设置单个上传文件的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。该方法有一个对应的读方法:publiclong geFileSizeMax()方法。

       在请求解析的过程中,如果单个上传文件的大小超过了setFileSizeMax方法的设置值,将会抛出FileUploadBase内部定义的FileSizeLimitExceededException异常(FileUploadException的子类)

3) public ListparseRequest(javax.servlet.http.HttpServletRequest req)

       parseRequest 方法是ServletFileUpload类的重要方法,它是对HTTP请求消息体内容进行解析的入口方法。它解析出FORM表单中的每个字段的数据,并将它们分别包装成独立的FileItem对象,然后将这些FileItem对象加入进一个List类型的集合对象中返回。

       该方法抛出FileUploadException异常来处理诸如文件尺寸过大、请求消息中的实体内容的类型不是“multipart/form-data”、IO异常、请求消息体长度信息丢失等各种异常。每一种异常都是FileUploadException的一个子类型。

4) public FileItemIterator getItemIterator(HttpServletRequest request)

       getItemIterator方法和parseRequest 方法基本相同。但是getItemIterator方法返回的是一个迭代器,该迭代器中保存的不是FileItem对象,而是FileItemStream对象,如果你希望进一步提高新能,你可以采用getItemIterator方法,直接获得每一个文件项的数据输入流,做底层处理;如果性能不是问题,你希望代码简单,则采用parseRequest方法即可。

5) public stiatc booleanisMultipartContent(HttpServletRequest req)

       isMultipartContent方法方法用于判断请求消息中的内容是否是“multipart/form-data”类型,是则返回true,否则返回falseisMultipartContent方法是一个静态方法,不用创建ServletFileUpload类的实例对象即可被调用。

6) getFileItemFactory()setFileItemFactory(FileItemFactory)

       方法继承自FileUpload类,用于设置和读取fileItemFactory属性。

7) public voidsetProgressListener(ProgressListener pListener)

      设置文件上传进度监听器。该方法有一个对应的读取方法:ProgressListenergetProgressListener()

8) public void setHeaderEncoding()

       在文件上传请求的消息体中,除了普通表单域的值是文本内容以外,文件上传字段中的文件路径名也是文本,在内存中保存的是它们的某种字符集编码的字节数组,Apache文件上传组件在读取这些内容时,必须知道它们所采用的字符集编码,才能将它们转换成正确的字符文本返回。

       setHeaderEncoding方法继承自FileUploadBase类,用于设置上面提到的字符编码。如果没有设置,则对应的读方法getHeaderEncoding()方法返回null,将采用HttpServletRequest设置的字符编码,如果HttpServletRequest的字符编码也为null,则采用系统默认字符编码。可以通过一下语句获得系统默认字符编码:

        System.getProperty("file.encoding"));

 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值