jsp表单文件上传

一、文件上传的前提

a、提供form表单,method必须是post

b、form表单的enctype必须是multipart/form-data(默认是:application/x-www-form-urlencoded)

注:服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。

c、提供input type="file"类的上传输入域

二、fileupload准备工作

a、fileupload的jar包:核心包(commons-fileupload.jar),依赖包(commons-io.jar)

b、fileupload组件使用步骤

    1.创建工厂类DiskFileItemFactory对象:

       DiskFileItemFactory factory = new DiskFileItemFactory()

     2.使用工厂创建解析器对象:

       ServletFileUpload fileUpload = new ServletFileUpload(factory)

    3.使用解析器来解析request对象:

       List<FileItem> list = fileUpload.parseRequest(request)

d、FileItem初步认识

    1、对象对应一个表单项(表单字段)。可以是文件字段或普通字段

    2、boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段

    3、String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username

    4、String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件

    5、String getName():获取文件字段的文件名称(a.txt)

    6、String getContentType():获取上传的文件的MIME类型,例如:text/plain

    7、int getSize():获取上传文件的大小

    8、InputStream getInputStream():获取上传文件对应的输入流

    9、void write(File):把上传的文件保存到指定文件中

    10、delete() 删除临时文件

三、需要注意的一些问题

a、安全(路径)问题:为保证服务器的安全,把保存上传文件的目录放在用户直接访问不到的地方,一般置于/WEB-INF/upload下

b、文件同名与文件夹中文件过多问题:

     1、文件名前+UUID

     2、创建子目录 按照日期进行打散存储目录,每天上传的文件的放在一个目录之下,适合文件不是特别多的情况

     3、用文件名的hashCode计算打散的存储目录:二级目录,适合特别多的情况

c、限制文件的大小:web方式不适合上传大的文件

     1、单个文件大小:ServletFileUpload.setFileSizeMax(1024*1024*5)    //单个文件不超过5M.

     2、多文件上传:ServletFileUpload.setSizeMax(字节)

d、处理中文乱码: 文件上传对象时 fileUpload.setHeaderEncoding("utf-8");   获取字段内容 item.getString("utf-8");

e、设置临时文件的存放位置:factory.setRepository(new File("f:\\filestemp"));//创建工厂类对象时设置,地址要已存在。

临时文件的删除:item.delete();

f、写文件已经封装好代码:item.write,而且具有自动删除临时文件的功能

四、代码实现

a、我们先新建一个简单的jsp文件,例如:

<body>
    <form enctype="multipart/form-data" action="${pageContext.request.contextPath }/servlet/UploadServlet" method="post">
    	<input type="text" name="info"></br>
    	<input type="file" name="files"></br>
    	<input type="file" name="photo"></br>
    	<input type="submit" value="提交">
    </form>
</body>

uploadServlet实现:
package com.zgf.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
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.FileUploadBase;
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.FilenameUtils;

import com.zgf.util.UUIDUtil;

public class UploadServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		//先判断表单提交数据类型
		boolean isMultipartForm = ServletFileUpload.isMultipartContent(request);//Content-Type  multipart/form-data

		if(!isMultipartForm)
			throw new RuntimeException("Your form's Content-Type is not multipart/form-data.");
		
		//创建工厂类对象
		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setRepository(new File("f:\\filestemp"));//设置临时文件的存放位置
		//创建文件上传对象
		ServletFileUpload fileUpload = new ServletFileUpload(factory);
		fileUpload.setHeaderEncoding("utf-8");//处理上传的中文乱码
		
		try {
			fileUpload.setFileSizeMax(1024*1024*3);//设置上传的文件的大小不能超过3M
			fileUpload.setSizeMax(1024*1024*5);//控制上传的文件的总大小
			
			//把表单提交过来的数据解析,把每个数据项封装成 FileItem对象----忘了,嘿嘿
			List<FileItem> fileItems = fileUpload.parseRequest(request);
			//获取每项数据
			for(FileItem item:fileItems){
				//判断是否是普通的数据项
				if(item.isFormField()){
					processFormField(item);
				}else{
					processFileUpload(item);
				}
			}
			
		}catch(FileUploadBase.SizeLimitExceededException e){
			System.out.println("上传的文件的总大小超过了5M");
		}catch(FileUploadBase.FileSizeLimitExceededException e){
			System.out.println("警告,文件不能超过3M");
		}
		catch (FileUploadException e) {
			e.printStackTrace();
		}	
	}
    //处理上传文件的方法
	private void processFileUpload(FileItem item) {
		
		//在应用的目录下创建存储上传的文件的目录
		//把目录创建在WEB-INF下是为了安全
		String storeDirectory = this.getServletContext().getRealPath("/WEB-INF/upload");
		File realDirectory = new File(storeDirectory);
		if(!realDirectory.exists())
			realDirectory.mkdirs();
		
		try {
			//读取文件的读取流
			InputStream in = item.getInputStream();
			
			//得到上传文件名
			String fileName = item.getName();//ie浏览器 F:\pic\deng2.jpg 火狐  deng2.jpg
			//截取文件名
			//fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
			fileName = FilenameUtils.getName(fileName);//使用工具类处理文件名
			
			//处理文件名同名的问题
			fileName = UUIDUtil.getUUID()+"_"+fileName;
			
			//处理把文件放在不同的文件夹下
			String childDirectory = getChildDirectory2(realDirectory,fileName);//"2016-09-30"
			
			File fileDir = new File(realDirectory,childDirectory+File.separator+fileName);
			FileOutputStream fos = new FileOutputStream(fileDir);
			
			byte[] arr = new byte[1024];
			int len = 0;
			while((len=in.read(arr))!=-1)
			{
				fos.write(arr,0,len);
			}
			
			//删除临时文件
			item.delete();
			
			in.close();
			fos.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}	
	
	//创建子目录:用哈希值    
	private String getChildDirectory2(File realDirectory, String fileName) {
		int hashCode = fileName.hashCode();
		String code = Integer.toHexString(hashCode);//把哈希值转成16进制
		
		String childDirectory = code.charAt(0)+File.separator+code.charAt(1);//  a/b a/a a/c a/d  b/a b/b b/c
		File dir = new File(realDirectory,childDirectory);
		if(!dir.exists())
			dir.mkdirs();
		
		return childDirectory;
	}
	//创建子目录:用时间
	private String getChildDirectory(File realDirectory) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date date = new Date();
		String time = sdf.format(date);// "2016-10-05"
		
		File dir = new File(realDirectory,time);
		if(!dir.exists())
		    dir.mkdirs();
		return time;
	}
	//处理普通表单项的方法
	private void processFormField(FileItem item) {
		//得到名字--jsp中文本框的名字
		String name = item.getFieldName();
		//得到值 
		String value ="";
		try {
			value = item.getString("utf-8");//处理中文乱码
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		System.out.println(name+"="+value);
	}
	


	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request,response);
	}

}

代码优化:
uploadServlet实现:
package com.zgf.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
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.FileUploadBase;
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.FilenameUtils;

import com.zgf.util.UUIDUtil;

public class UploadServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		//判断表单提交数据类型
		boolean isMultipartForm = ServletFileUpload.isMultipartContent(request);//Content-Type  multipart/form-data
		if(!isMultipartForm)
			throw new RuntimeException("Your form's Contet-Type is not multipart/form-data.");
		
		//创建工厂类对象
		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setRepository(new File("f:\\filestemp"));//设置临时文件的存放位置--事先存在
		//创建文件上传对象
		ServletFileUpload fileUpload = new ServletFileUpload(factory);
		fileUpload.setHeaderEncoding("utf-8");//处理上传的中文乱码
		
		try {
			fileUpload.setFileSizeMax(1024*1024*3);//设置上传的单个文件的大小不能超过3M
			fileUpload.setSizeMax(1024*1024*5);//控制上传的文件的总大小
			
			//把表单提交过来的数据解析,把每个数据项封装成 FileItem对象
			List<FileItem> fileItems = fileUpload.parseRequest(request);
			//获取每项数据
			for(FileItem item:fileItems){
				//判断是否是普通的数据项
				if(item.isFormField()){
					processFormField(item);
				}else{
					processFileUpload(item);
				}
			}
			
		}catch(FileUploadBase.SizeLimitExceededException e){
			System.out.println("上传的文件的总大小超过了5M");
		}catch(FileUploadBase.FileSizeLimitExceededException e){
			System.out.println("警告,文件不能超过3M");
		}
		catch (FileUploadException e) {
			e.printStackTrace();
		}
		
		
	}
    //处理上传文件的方法 
	private void processFileUpload(FileItem item) {
		
		//在应用的目录下创建存储上传的文件的目录
		//把目录创建在WEB-INF下是为了安全
		String storeDirectory = this.getServletContext().getRealPath("/WEB-INF/upload");
		File realDirectory = new File(storeDirectory);
		if(!realDirectory.exists())
			realDirectory.mkdirs();
		try {
			//读取文件的读取流
			//InputStream in = item.getInputStream();
			
			//得到上传文件名
			String fileName = item.getName();//ie浏览器 F:\pic\deng2.jpg 火狐  deng2.jpg
			//截取文件名
			//fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
			fileName = FilenameUtils.getName(fileName);//使用工具类处理文件名
			
			//处理文件名同名的问题
			fileName = UUIDUtil.getUUID()+"_"+fileName;
			
			//处理把文件放在不同的文件夹下-- getChildDirectory
			//String childDirectory = getChildDirectory2(realDirectory,fileName);//"2016-10-05"
			String childDirectory = getChildDirectory(realDirectory);
			
			//自动删除临时文件的功能--路径:WEB-INF/upload  8/3 / UUID_哈哈.txt 
			item.write(new File(realDirectory,childDirectory+File.separator+fileName));
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}	
	
	//创建子目录:用哈希值    
	private String getChildDirectory2(File realDirectory, String fileName) {	
		int hashCode = fileName.hashCode();	
		String code = Integer.toHexString(hashCode);//把哈希值转成16进制
		
		String childDirectory = code.charAt(0)+File.separator+code.charAt(1);//  a/b a/a a/c a/d  b/a b/b b/c
		File dir = new File(realDirectory,childDirectory);
		
		if(!dir.exists())
			dir.mkdirs();	
		return childDirectory;
	}
	//创建子目录:用时间
	private String getChildDirectory(File realDirectory) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date date = new Date();
		String time = sdf.format(date);// "2016-09-30"
		
		File dir = new File(realDirectory,time);
		if(!dir.exists())
		    dir.mkdirs();
		return time;
	}
	//处理普通表单项的方法
	private void processFormField(FileItem item) {
		//得到名字
		String name = item.getFieldName();
		//得到值
		String value ="";
		try {
			value = item.getString("utf-8");//处理中文乱码
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		System.out.println(name+"="+value);
	}
	


	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request,response);
	}

}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值