赞
踩
拷贝jar包:commons-fileupload.jar commons-io.jar 具体参考
http://commons.apache.org/proper/commons-fileupload/using.html
public void setRepository(File repository):设置临时文件的存放目录
public void setSizeThreshold(int sizeThreshold):设置缓存的大小
专题:关于临时文件
虚拟内存的概念:当内存中的空间不够用的时候,这个时候,会在磁盘上划分一部分区域作为虚拟内存,将内存中不经常使用的文件先保存到虚拟内存中。所以虚拟内存是磁盘上的一部分存储空间。
为什么启用缓存呢?减少与硬盘的交互次数,最终还是要存放到磁盘上的 ,存放到内存中,速度更快。 所以上传的文件首先是存放到内存中的缓存中的,
如果是一个100M大小的文件,那么每次获取10Kb,到内存中,然后存放到临时文件中,当所有的100M都存放到临时文件中后,然后再把临时文件中的文件全部放到最终文件中,最后把临时文件进行删除。
临时文件需要在代码中指定来实现,调用item.delete()来删除。 FileItem item = new DiskFileItemFactory()
临时文件的删除问题:
文件上传时,自己用IO流处理的文件,一定要在流关闭的时候删除临时文件,FileItem.delete()
建议使用:FileItem.writer(File f)会自动删除临时文件
3.2乱码问题
1) 普通字段乱码
filedValue = item.getString("UTF-8"); 如果提交的是输出框的值,那么需要通过FileItem.getString(String charset);编码需要和客户端一致
2)文件名乱码
可以通过requset.setCharacterEncoding("UTF-8");仅能够解决报文中的请求头的问题,不能解决正文的编码问题
3)解决文件名重名的问题
通过UUID来命名文件名fileName = UUID.randomUUID()+"_"+ FilenameUtils.getName(fileName);
4)保证服务器的安全
为了防止用户上传的文件,通过路径可以直接访问到该文件,造成服务器的漏洞,bat文件等,需要将用户上传的文件存放到用户不能直接访问的地方,如:
String storeDirectoryPath = getServletContext().getRealPath("/WEB-INF/files"); 将文件放到WEB-INF目录下面。
5)避免一个文件夹中的文件过多
解决方法:分目录存储
参考实现:
1)按照日期分目录存储
2)通过文件名的HashCode来设定文件夹
//上传字段
private void processUploadField(FileItem item) {
try {
String fileName = item.getName(); //上传文件的名称 C:\Users\zhangjianbo\Desktop\a.txt a.txt
//截取文件名
if(fileName!=null){
fileName = UUID.randomUUID()+"_"+ FilenameUtils.getName(fileName);
}
// //分目录存储:日期解决方案
// Date now = new Date();
// DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
// String time = df.format(now);
//通过文件名的hashCode来实现
String childDiretory = makeChildDirectory(getServletContext().getRealPath("/WEB-INF/files/"),fileName);
//把文件存到服务器的某个目录中
String storeDirectoryPath = getServletContext().getRealPath("/WEB-INF/files/"+childDiretory);
File storeDirectory = new File(storeDirectoryPath);
if(!storeDirectory.exists()){
storeDirectory.mkdirs();
}
item.delete();//表示删除临时文件
item.write(new File(storeDirectoryPath +File.separator+ fileName));// File Item中存在write方法
} catch (Exception e) {
throw new RuntimeException("上传失败,请重试");
}
}
private String makeChildDirectory(String realPath, String fileName) {
int hashCode = fileName.hashCode();
int dir1 = hashCode&0xf;//取文件名的二进制的1~4位
int dir2 = (hashCode&0xf0)>>4; //获取5~8
String directory = "" + dir1 + File.separator +dir2;
File file = new File(realPath,directory);
if (!file.exists()){
file.mkdirs();
}
return directory;
}
3.6 限制文件上传的大小,并给出友好提示
Web方式不适合传输较大的文件
1)单文件大小(一般限制4M)
//创建DiskFileItemFactory
DiskFileItemFactory dfif = new DiskFileItemFactory();
ServletFileUpload parser = new ServletFileUpload(dfif);
parser.setFileSizeMax(4*1024*1024); //设置单个文件上传的大小
parser.setSizeMax(6*1024*1024); //多文件上传时的总大小限制
List<FileItem> items = null ;
//解析内容
try {
items = parser.parseRequest(request);
}catch(FileUploadBase.FileSizeLimitExceededException e){ //该异常为一个静态内部类
out.write("上传的文件超出了4M");
return;
}
catch(FileUploadBase.SizeLimitExceededException e){ //该异常为一个静态内部类
out.write("总文件大小超出了6M");
return;
}
catch (FileUploadException e) {
throw new RuntimeException("解析上传内容失败,请重新试一下");
}
2)总文件大小(多文件上传)
parser.setSizeMax(6*1024*1024); //多文件上传时的总大小限制
3.7 限制上传文件的类型
通过扩展名+ 文件的MIME类型来进行限制
// 扩展名
String extension = FilenameUtils.getExtension(fileName);
// MIME类型 -- 判断MIME类型仅限于IE浏览器
String contentType = item.getContentType();
if (contentType.startsWith("image/")) {
MIME类型:Web请求文件中的Content-Type类型,就表示MIME类型
由大类型/小类型组成,我们只需要判断大类型即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。