javaweb文件上传的九大问题_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > javaweb文件上传的九大问题

javaweb文件上传的九大问题

 2017/10/9 12:43:07  钮晓东  程序员俱乐部  我要评论(0)
  • 摘要:1、如何保证服务器的安全把保存上传文件的目录放到WEB-INF目录中。2、中文乱码问题2.1普通字段的中文请求参数Stringvalue=FileItem.getString("UTF-8");2.2上传的文件名是中文解决办法:request.setCharacterEncoding("UTF-8");3、重名文件被覆盖的问题System.currentMillions()+"_"+a.txt(乐观)UUID+"_"+a.txt:保证文件名唯一4、分目录存储上传的文件方式一
  • 标签:javaweb Web 上传 文件 Java 问题
1、如何保证服务器的安全
把保存上传文件的目录放到WEB-INF目录中。

2、中文乱码问题
2.1普通字段的中文请求参数
String value = FileItem.getString("UTF-8");
2.2上传的文件名是中文
解决办法:request.setCharacterEncoding("UTF-8");

3、重名文件被覆盖的问题
System.currentMillions()+"_"+a.txt(乐观)
        UUID+"_"+a.txt:保证文件名唯一

4、分目录存储上传的文件
方式一:当前日期建立一个文件夹,当前上传的文件都放到此文件夹中。
例如:生成一个2014-10-6的文件夹
class="java" name="code">Date date = new Date();
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
String s = df.format(date);
String path = storePath+"\\"+s;
File file = new File(path);
if(!file.exists()){
    file.mkdirs();//创建多级目录,mkdir只创建一级目录
}
return path;//文件夹的地址

方式二:利用文件名的hash码打散目录来存储。
int hashCode = fileName.hashCode();

1001 1010 1101 0010 1101 1100 1101 1010
hashCode&0xf   0000 0000 0000 0000 0000 0000 0000 1111 &
---------------------------------------------
0000 0000 0000 0000 0000 0000 0000 1010   取hashCode的后4位
0000~1111:整数0~15共16个

1001 1010 1101 0010 1101 1100 1101 1010
(hashCode&0xf0) 0000 0000 0000 0000 0000 0000 1111 0000  &
--------------------------------------------
0000 0000 0000 0000 0000 0000 1101 0000  >>4
--------------------------------------------
0000 0000 0000 0000 0000 0000 0000 1101
     0000~1111:整数0~15共16个

5、限制用户上传的文件类型
通过判断文件的扩展名来限制是不可取的。
通过判断其Mime类型才靠谱。FileItem.getContentType();

6、如何限制用户上传文件的大小
6.1单个文件大小限制。超出了大小友好提示
异常进行提示:
org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException
6.2总文件大小限制。超出了大小友好提示
抓异常进行提示:
org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededExcept

7、临时文件的问题
commons-fileupload组件不会删除超出缓存的临时文件。
FileItem.delete()方法删除临时文件。但一定要在关闭流之后。

8、多个文件上传时,没有上传内容的问题
if(fileName==null||"".equals(fileName.trim())){
continue;
}


9、上传进度检测
ServletFileUpload注册一个进度监听器即可,把上传进度传递给页面去显示
//pBytesRead:当前以读取到的字节数
//pContentLength:文件的长度
//pItems:第几项
public void update(long pBytesRead, long pContentLength,
				int pItems) {
System.out.println("已读取:"+pBytesRead+",文件大小:"+pContentLength+",第几项:"+pItems);
}


完整实例 :
表单:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP '1.jsp' starting page</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
 <form action="${pageContext.request.contextPath}/servlet/UploadServlet3" method="post" enctype="multipart/form-data">
   用户名<input type="text" name="username"/> <br/>
   <input type="file" name="f1"/><br/>
   <input type="file" name="f2"/><br/>
   <input type="submit" value="保存"/>
 </form>
  </body>
</html>


UploadServlet3
package com.mair.upload;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.logging.SimpleFormatter;

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.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet3 extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		//设置编码
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter pw = response.getWriter();
		try {
			//设置系统环境
			DiskFileItemFactory factory = new DiskFileItemFactory();
			//文件存储的路径
			String storePath = getServletContext().getRealPath("/WEB-INF/files");
			//判断传输方式  form  enctype=multipart/form-data
			boolean isMultipart = ServletFileUpload.isMultipartContent(request);
			if(!isMultipart)
			{
			   	pw.write("传输方式有错误!");
			   	return;
			}
			ServletFileUpload upload = new ServletFileUpload(factory);
			upload.setFileSizeMax(4*1024*1024);//设置单个文件大小不能超过4M
			upload.setSizeMax(4*1024*1024);//设置总文件上传大小不能超过6M
			//监听上传进度
			upload.setProgressListener(new ProgressListener() {

				//pBytesRead:当前以读取到的字节数
 				//pContentLength:文件的长度
 				//pItems:第几项
				public void update(long pBytesRead, long pContentLength,
						int pItems) {
					System.out.println("已读去文件字节 :"+pBytesRead+" 文件总长度:"+pContentLength+"   第"+pItems+"项");
					
				}
			});
			//解析
			List<FileItem> items = upload.parseRequest(request);
			for(FileItem item: items)
			{
				if(item.isFormField())//普通字段,表单提交过来的
				{
					String name = item.getFieldName();
					String value = item.getString("UTF-8");
					System.out.println(name+"=="+value);
				}else
				{
//					String mimeType = item.getContentType(); 获取上传文件类型
//					if(mimeType.startsWith("image")){
					InputStream in =item.getInputStream();
					String fileName = item.getName(); 
					if(fileName==null || "".equals(fileName.trim()))
					{
						continue;
					}
					fileName = fileName.substring(fileName.lastIndexOf("\\")+1);
					fileName = UUID.randomUUID()+"_"+fileName;
					
					//按日期来建文件夹
					String newStorePath = makeStorePath(storePath);
					String storeFile = newStorePath+"\\"+fileName;
					OutputStream out = new FileOutputStream(storeFile);
					byte[] b = new byte[1024];
					int len = -1;
					while((len = in.read(b))!=-1)
					{
				         out.write(b,0,len);		
					}
					in.close();
					out.close();
					item.delete();//删除临时文件
				}
			  }
//			}
		}catch(org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException e){ 
		      //单个文件超出异常
			pw.write("单个文件不能超过4M");
		}catch(org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException e){
			//总文件超出异常
			pw.write("总文件不能超过6M");
			
		}catch (FileUploadException e) {
			e.printStackTrace();
		}
		
		

	}
       //用日期生成的目录,如果想用hashcode,后面
	private String makeStorePath(String storePath) {
		
		Date date = new Date();
		DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
		String s = df.format(date);
		String path = storePath+"\\"+s;
		File file = new File(path);
		if(!file.exists())
		{
			file.mkdirs();//创建多级目录,mkdir只创建一级目录
		}
		return path;
		 
	}

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

}

用hashcode生成目录:只需要改写一下makeStorePath(String storePath, String fileName)函数
private String makeStorePath(String storePath, String fileName) {
		int hashCode = fileName.hashCode();
		int dir1 = hashCode & 0xf;// 0000~1111:整数0~15共16个
		int dir2 = (hashCode & 0xf0) >> 4;// 0000~1111:整数0~15共16个

		String path = storePath + "\\" + dir1 + "\\" + dir2; // WEB-INF/files/1/12
		File file = new File(path);
		if (!file.exists())
			file.mkdirs();

		return path;
	}

发表评论
用户名: 匿名