Java学习之文件上传的注意细节
来源:互联网 发布:论文相似性检测软件 编辑:程序博客网 时间:2024/06/09 17:06
上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的
1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
4、要限制上传文件的最大值。
5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
针对上述提出的5点细节问题,我们来改进一下UploadHandleServlet,改进后的代码如下:
1 package me.gacl.web.controller; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.util.List; 8 import java.util.UUID; 9 10 import javax.servlet.ServletException; 11 import javax.servlet.http.HttpServlet; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 import org.apache.commons.fileupload.FileItem; 15 import org.apache.commons.fileupload.FileUploadBase; 16 import org.apache.commons.fileupload.ProgressListener; 17 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 18 import org.apache.commons.fileupload.servlet.ServletFileUpload; 19 20 /** 21 * @ClassName: UploadHandleServlet 22 * @Description: TODO(这里用一句话描述这个类的作用) 23 * 24 * 25 * 26 */ 27 public class UploadHandleServlet extends HttpServlet { 28 29 public void doGet(HttpServletRequest request, HttpServletResponse response) 30 throws ServletException, IOException { 31 //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 32 String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); 33 //上传时生成的临时文件保存目录 34 String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp"); 35 File tmpFile = new File(tempPath); 36 if (!tmpFile.exists()) { 37 //创建临时目录 38 tmpFile.mkdir(); 39 } 40 41 //消息提示 42 String message = ""; 43 try{ 44 //使用Apache文件上传组件处理文件上传步骤: 45 //1、创建一个DiskFileItemFactory工厂 46 DiskFileItemFactory factory = new DiskFileItemFactory(); 47 //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。 48 factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB 49 //设置上传时生成的临时文件的保存目录 50 factory.setRepository(tmpFile); 51 //2、创建一个文件上传解析器 52 ServletFileUpload upload = new ServletFileUpload(factory); 53 //监听文件上传进度 54 upload.setProgressListener(new ProgressListener(){ 55 public void update(long pBytesRead, long pContentLength, int arg2) { 56 System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead); 57 /** 58 * 文件大小为:14608,当前已处理:4096 59 文件大小为:14608,当前已处理:7367 60 文件大小为:14608,当前已处理:11419 61 文件大小为:14608,当前已处理:14608 62 */ 63 } 64 }); 65 //解决上传文件名的中文乱码 66 upload.setHeaderEncoding("UTF-8"); 67 //3、判断提交上来的数据是否是上传表单的数据 68 if(!ServletFileUpload.isMultipartContent(request)){ 69 //按照传统方式获取数据 70 return; 71 } 72 73 //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB 74 upload.setFileSizeMax(1024*1024); 75 //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB 76 upload.setSizeMax(1024*1024*10); 77 //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 78 List<FileItem> list = upload.parseRequest(request); 79 for(FileItem item : list){ 80 //如果fileitem中封装的是普通输入项的数据 81 if(item.isFormField()){ 82 String name = item.getFieldName(); 83 //解决普通输入项的数据的中文乱码问题 84 String value = item.getString("UTF-8"); 85 //value = new String(value.getBytes("iso8859-1"),"UTF-8"); 86 System.out.println(name + "=" + value); 87 }else{//如果fileitem中封装的是上传文件 88 //得到上传的文件名称, 89 String filename = item.getName(); 90 System.out.println(filename); 91 if(filename==null || filename.trim().equals("")){ 92 continue; 93 } 94 //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 95 //处理获取到的上传文件的文件名的路径部分,只保留文件名部分 96 filename = filename.substring(filename.lastIndexOf("\\")+1); 97 //得到上传文件的扩展名 98 String fileExtName = filename.substring(filename.lastIndexOf(".")+1); 99 //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法100 System.out.println("上传的文件的扩展名是:"+fileExtName);101 //获取item中的上传文件的输入流102 InputStream in = item.getInputStream();103 //得到文件保存的名称104 String saveFilename = makeFileName(filename);105 //得到文件的保存目录106 String realSavePath = makePath(saveFilename, savePath);107 //创建一个文件输出流108 FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);109 //创建一个缓冲区110 byte buffer[] = new byte[1024];111 //判断输入流中的数据是否已经读完的标识112 int len = 0;113 //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据114 while((len=in.read(buffer))>0){115 //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中116 out.write(buffer, 0, len);117 }118 //关闭输入流119 in.close();120 //关闭输出流121 out.close();122 //删除处理文件上传时生成的临时文件123 //item.delete();124 message = "文件上传成功!";125 }126 }127 }catch (FileUploadBase.FileSizeLimitExceededException e) {128 e.printStackTrace();129 request.setAttribute("message", "单个文件超出最大值!!!");130 request.getRequestDispatcher("/message.jsp").forward(request, response);131 return;132 }catch (FileUploadBase.SizeLimitExceededException e) {133 e.printStackTrace();134 request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");135 request.getRequestDispatcher("/message.jsp").forward(request, response);136 return;137 }catch (Exception e) {138 message= "文件上传失败!";139 e.printStackTrace();140 }141 request.setAttribute("message",message);142 request.getRequestDispatcher("/message.jsp").forward(request, response);143 }144 145 /**146 * @Method: makeFileName147 * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称148 * @Anthor:孤傲苍狼149 * @param filename 文件的原始名称150 * @return uuid+"_"+文件的原始名称151 */ 152 private String makeFileName(String filename){ //2.jpg153 //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名154 return UUID.randomUUID().toString() + "_" + filename;155 }156 157 /**158 * 为防止一个目录下面出现太多文件,要使用hash算法打散存储159 * @Method: makePath160 * @Description: 161 162 *163 * @param filename 文件名,要根据文件名生成存储目录164 * @param savePath 文件存储路径165 * @return 新的存储目录166 */ 167 private String makePath(String filename,String savePath){168 //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址169 int hashcode = filename.hashCode();170 int dir1 = hashcode&0xf; //0--15171 int dir2 = (hashcode&0xf0)>>4; //0-15172 //构造新的保存目录173 String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5174 //File既可以代表文件也可以代表目录175 File file = new File(dir);176 //如果目录不存在177 if(!file.exists()){178 //创建目录179 file.mkdirs();180 }181 return dir;182 }183 184 public void doPost(HttpServletRequest request, HttpServletResponse response)185 throws ServletException, IOException {186 187 doGet(request, response);188 }189 }
针对上述提出的5点小细节问题进行改进之后,我们的文件上传功能就算是做得比较完善了。
0 0
- Java学习之文件上传的注意细节
- 上传文件中应当注意的细节
- 上传文件中应当注意的细节(二)
- 使用Commons-fileupload组件实现文件上传的注意细节
- java文件上传注意的问题
- java之上传文件的细节(都可以在源码体现,抽取出来讲呗)
- 学习java应该注意的一些细节(转载)
- [置顶]关于使用input type=file 标签上传文件的注意细节(上传文件 无法获取文件 问题)
- 上传文件的处理细节
- 上传文件的一些细节:
- 上传文件的一些细节
- 上传文件的处理细节
- 上传文件的一些细节
- 文件上传的细节问题
- 【PHP】在php文件上传时需要注意的几个细节
- C++学习小结之注意细节点
- 文件读写时注意的细节问题
- 上传文件的处理细节、文件下载
- xz文件解压
- 线程安全问题(银行取钱问题)、同步代码块、同步方法
- Windows下使用_access和_stat判断文件和目录是否存在的区别
- 2D骨骼动画软件spine与在unity3d中使用
- mysql 备份与还原(一)
- Java学习之文件上传的注意细节
- jquery 读取XML 文件 并按时间进行排序
- Java线程池ThreadPoolExecutor的实例
- [BZOJ1029][JSOI2007]建筑抢修(multiset)
- 解决adapter.getView()方法多次被调用,导致listView卡顿的原因。
- [JSOI2007]建筑抢修
- 线程——并行
- [OpenJudge] 2.5基本算法之搜索 取石子游戏分析
- Fragment基本使用(一)——静态加载布局