Java文件上传

一般表单的enctype属性默认值为application/x-www-form-urlencoded,不具备上传文件的功能,所以要改为:multipart/form-data,并且只能用post方式提交。这个过程中将编码方式改为了MIME,它将普通参数和上传的附件一块发送给服务端,再用request的getParameter方法获取参数就失效了。 

一、手动上传方式

       Jsp页面写法

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form method="post" action="${pageContext.request.contextPath}/MoudleFileUpload" enctype="multipart/form-data"> 
		<table>
			<caption>文件上传</caption>
			<tr>
				<td>用户名:</td>
				<td><input type="text" name="username"/></td>
			</tr>
			<tr>
				<td>文件:</td>
				<td><input type="file" name="file"/></td>
			</tr>
			<tr>
				<td colspan="2" align="center"><input type="submit" value="submit"/></td>
			</tr>
		</table>
	</form>
</body>
</html>

         Servlet写法

package com.hncj.test;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/NormalUpload")
public class NormalUpload extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//String username = request.getParameter("username");  返回null
		ServletInputStream is = request.getInputStream();
		int len = 0;
		byte[]arr = new byte[1024];
		while((len = is.read(arr))>0) {
			System.out.println(new String(arr,0,len));
		}
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

        测试结果中,不仅包含了输入的用户名信息,还包含文件内容。

        这种方法的弊端:存在文件名乱码问题,提交的普通参数和文件不好分离......

二、组件方式

        需要使用Apache的两个jar包:commons-fileupload-1.3.3.jar   commons-io-2.6.jar         

        可以在官网下载:Apache      

        代码如下:

package com.hncj.test;

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@WebServlet("/MoudleFileUpload")
public class MoudleFileUpload extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String storePath = this.getServletContext().getRealPath("/WEB-INF/store");
		String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
		File store = new File(storePath);
		File temp = new File(tempPath);
		if(!store.exists()) {
			store.mkdir();
		}
		if(!temp.exists()) {
			temp.mkdir();
		}
		//创建文件工厂类
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//设置缓冲文件存储路径
		factory.setRepository(temp);
		//设置文件的大小限制
		factory.setSizeThreshold(30*1024*1024);
		//创建文件上传类
		ServletFileUpload upload = new ServletFileUpload(factory);
		//解决文件名乱码问题
		upload.setHeaderEncoding("UTF-8");
		upload.setProgressListener(new ProgressListener() {
			
			@Override
			public void update(long pBytesRead, long pContentLength, int pupload) {
				System.out.println("文件总大小:"+pContentLength+"字节 你已经上传:"+pBytesRead);
			}
		});
		if(!upload.isMultipartContent(request)) {
			//不是MIME传输方式
			return;
		}else {
			try {
				//获取数据集合
				List<FileItem> fileItems = upload.parseRequest(request);
				for(FileItem item : fileItems) {
					if(item.isFormField()) {
						//不是文件类型,而是普通提交数据
						System.out.println(item.getString("UTF-8"));
					}else {
						/*String content = item.getString("UTF-8");输出文件内容*/
						
						//不同浏览器获取的文件名不同,有的是具体位置,有的直接是文件的名字,所以要规范一下
						String name = item.getName();
						String fileName = name.substring(name.lastIndexOf("\\")+1);
						InputStream is = item.getInputStream();
						FileOutputStream fos = new FileOutputStream(store+"/"+fileName);
						int len = 0;
						byte[]arr = new byte[1024];
						while((len = is.read(arr))>0) {
							fos.write(arr, 0, len);
						}
						fos.close();
						is.close();
						//删除下载时产生的临时文件,这步很重要
						item.delete();
					}
				}
			} catch (FileUploadException e) {
				e.printStackTrace();
			}
		}
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req,resp);
	}
}

为了防止不同用户提交相同文件名的文件,可以使用UUID值加上真实文件名的文件名修改方式。

同时为了防止同一目录下文件过多,可是采用生成多级目录分散存储的方式。

package com.hncj.test;

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@WebServlet("/MoudleFileUpload")
public class MoudleFileUpload extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String storePath = this.getServletContext().getRealPath("/WEB-INF/store");
		String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
		File store = new File(storePath);
		File temp = new File(tempPath);
		if(!store.exists()) {
			store.mkdir();
		}
		if(!temp.exists()) {
			temp.mkdir();
		}
		//创建文件工厂类
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//设置缓冲文件存储路径
		factory.setRepository(temp);
		//设置文件的大小限制
		factory.setSizeThreshold(30*1024*1024);
		//创建文件上传类
		ServletFileUpload upload = new ServletFileUpload(factory);
		//解决文件名乱码问题
		upload.setHeaderEncoding("UTF-8");
		upload.setProgressListener(new ProgressListener() {
			
			@Override
			public void update(long pBytesRead, long pContentLength, int pupload) {
				System.out.println("文件总大小:"+pContentLength+"字节 你已经上传:"+pBytesRead);
			}
		});
		if(!upload.isMultipartContent(request)) {
			//不是MIME传输方式
			return;
		}else {
			try {
				//获取数据集合
				List<FileItem> fileItems = upload.parseRequest(request);
				for(FileItem item : fileItems) {
					if(item.isFormField()) {
						//不是文件类型,而是普通提交数据
						System.out.println(item.getString("UTF-8"));
					}else {
						/*String content = item.getString("UTF-8");输出文件内容*/
						
						//不同浏览器获取的文件名不同,有的是具体位置,有的直接是文件的名字,所以要规范一下
						String name = item.getName();
						String fileName = name.substring(name.lastIndexOf("\\")+1);
						String uuidName = getUUIDName(fileName);  //加上UUID
						String savePath = getRandomDir(storePath, uuidName);  //加上两级目录
						InputStream is = item.getInputStream();
						FileOutputStream fos = new FileOutputStream(savePath+"/"+uuidName);
						int len = 0;
						byte[]arr = new byte[1024];
						while((len = is.read(arr))>0) {
							fos.write(arr, 0, len);
						}
						fos.close();
						is.close();
						//删除下载时产生的临时文件,这步很重要
						item.delete();
					}
				}
			} catch (FileUploadException e) {
				e.printStackTrace();
			}
		}
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doGet(req,resp);
	}
	
	//加上UUID之后的文件名
	private String getUUIDName(String fileName) {
		return UUID.randomUUID()+"_"+fileName;
	}
	
	
	//加上2级目录
	private String getRandomDir(String storePath,String uuidName) {
		int hashCode = uuidName.hashCode();
		int dir1 = hashCode & 0xf;
		int dir2 = (hashCode>>4) & 0xf;
		String savePath = storePath+"/"+dir1+"/"+dir2;
		File f = new File(savePath);
		if(!f.exists()) {
			boolean flag = f.mkdirs();  //特别注意,mkdirs(),目录和文件一定要先创建父目录,再创建子目录,坑啊
			                            //刚开始一直报FileNotFound和IOException
		}
		return f.getPath();
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值