文件上传下载及jar包封装
表单要求
对于表单上传,要求使用post请求方式,并且 enctype必须是如下类型
method="post" enctype="multipart/form-data"
- 1
- 2
- 3
- 4
上传代码
当表单中的类型指定为multipart/form-data 时,无法通过getParameter获取请求参数,使用第三方jar包
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");//
// 但它可以解决上传文件 的文件名为中文的乱码问题
String storagePath = getServletContext().getRealPath("/image");
// 判断当前文件夹是否存在,如果不存在,就创建一个新的
File file = new File(storagePath);
if (!file.exists()) {
file.mkdirs();
}
// 判断表单是否是规定格式
boolean multipartContent = ServletFileUpload
.isMultipartContent(request);
// 如果不是规定格式,提示表单问题
if (!multipartContent) {
response.getWriter().write("表单有问题");
return;
}
// 获取一个能够去表单文件的工厂
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 创建上传的对象
ServletFileUpload servletFileUpload = new ServletFileUpload(
fileItemFactory);
try {
//解析请求-获取表单中的字段集合
List<FileItem> parseRequest = servletFileUpload
.parseRequest(request);
//遍历集合
for (FileItem fileItem : parseRequest) {
//判断是否是普通字段
if (fileItem.isFormField()) {
//获取字段名称
String fieldName = fileItem.getFieldName();
System.out.println(fieldName);
//获取字段value
String string = fileItem.getString("UTF-8");
System.out.println(string);
} else {
// 说明是上传的文件
String name = fileItem.getName();
// 自己拼接路径
String savePath = storagePath + "/"
+ name.substring(name.lastIndexOf("/") + 1);
// 开始读取文件,然后写入到存储的文件夹下
FileOutputStream fileOutputStream = new FileOutputStream(
new File(savePath));
//因为是文件,以流的形获取
InputStream inputStream = fileItem.getInputStream();
//使用工具类,读取表单中的文件,然后复制到输出流中去
IOUtils.copy(inputStream, fileOutputStream);
//关闭流
fileOutputStream.close();
inputStream.close();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
上传优化
1.得到上传的文件要保存的位置,如果不想被随便访问,请放置到WEB-INF文件夹下边
String storePath = getServletContext().getRealPath("/WEB-INF/images");
- 1
- 2
2.判断文件上传的类型,如果对于要求上传图片的需求,添加图片的限制
String mime = item.getContentType();//MIME类型 image/jpeg image/bmp if(mime.contains("image")){ if("".equals(item.getName())){ continue; }
- 1
- 2
- 3
- 4
- 5
- 6
3.文件名同名的问题,使用UUID生成一个唯一的随机名称
fileName = UUID.randomUUID().toString()+"_"+fileName;
- 1
- 2
4.分文件夹存储图片-按照日期方式存储图片
public String createDirByDate(String path){ DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); String dir = df.format(new Date()); File file = new File(path +File.separator+dir); if(!file.exists()){ file.mkdirs(); } return dir; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
5.分文件夹存储图片二-按照Hash值存储图片
public String createDirByHashCode(String path,String fileName){ int hashcode = fileName.hashCode();//得到一个字符串的hashcode码 " int dir1 = hashcode&0xf; //位与 得到一级子目录 (16个) int dir2 = (hashcode & 0xf0)>>4;// 得到的结果 String childPath = dir1+File.separator+dir2; File file = new File(path,childPath);//第一个参数是父目录,第二个参数是子目录 if(!file.exists()){ file.mkdirs(); } return childPath;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
}
String savePath = storePath+File.separator+createDirByHashCode(storePath,fileName)+File.separator+fileName;
- 1
- 2
文件下载
对于文件下载,主要分为两个步骤
第一步:设置下载的响应头
response.setHeader("Content-Dispostion", "attachment;fileName=" + URLEncoder.encode(name, "UTF-8"));
- 1
- 2
- 3
第二步:读取文件流,通过响应的输出流打给客户端
String name = realPath.substring(realPath.lastIndexOf("_")); response.setHeader("Content-Dispostion", "attachment;fileName=" + URLEncoder.encode(name, "UTF-8")); FileInputStream fileInputStream = new FileInputStream(new File( realPath)); ServletOutputStream outputStream = response.getOutputStream(); IOUtils.copy(fileInputStream, outputStream); fileInputStream.close(); outputStream.close();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
自行封装文件上传的jar包
对于像上传这样的常用功能,如果每次上传都写100 200行代码岂不是累屎,于是我们封装成工具类,来搞定这个事情
定义一个静态的上传方法,要求提供三个参数,存储路径,请求参数,要封装成的对象T
主要的代码和上传代码一致,不过,需要重点说的就是里边有一块反射的内容,对于T这个对象,要求在定义的时候就和表单中的字段名称一致,这样就可以做到通过反射属性名,来设置属性的值并不是多么高大上的东东…
public static <T> void upload(String storagePath, HttpServletRequest httpServletRequest, T t) { boolean multipartContent = ServletFileUpload .isMultipartContent(httpServletRequest); // 上传文件的工厂 FileItemFactory fileItemFactory = new DiskFileItemFactory(); // 临时文件 // 上传文件的对象 ServletFileUpload servletFileUpload = new ServletFileUpload( fileItemFactory); // 解析请求 try { List<FileItem> parseRequest = servletFileUpload .parseRequest(httpServletRequest); Class<? extends Object> tClazz = t.getClass(); // 遍历传递的数据集合 for (FileItem fileItem : parseRequest) { // 判断字段是什么类型 boolean formField = fileItem.isFormField(); // 普通类型 if (formField) { // 获取字段名--name -password // username ---反射 String name = fileItem.getFieldName(); String value = fileItem.getString("UTF-8"); Field field = tClazz.getDeclaredField(name); if (field != null) { // 暴力反射 field.setAccessible(true); field.set(t, value); } } else { // 上传的文件类型 // 文件的名称 c:/aa/ab.jpg // image/ab.jpg String name = fileItem.getName(); String fileName = name.substring(name.lastIndexOf("/") + 1); fileName = UUID.randomUUID() + "_" + fileName; // 获取流的信息 InputStream inputStream = fileItem.getInputStream(); // 文件最终存储到的位置 String targetPath = storagePath + "/" + createDirByHashCode(storagePath, fileName) + "/" + fileName; // 把流写到本地 FileOutputStream fileOutputStream = new FileOutputStream( new File(targetPath)); // pic Field field = tClazz.getDeclaredField(fileItem .getFieldName()); if (field != null) { // 暴力反射 field.setAccessible(true); field.set(t, targetPath); } IOUtils.copy(inputStream, fileOutputStream); inputStream.close(); fileOutputStream.close(); } } } catch (Exception e) { e.printStackTrace(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
顺便把下载的方法做一下简单封装,提供下载的路径,提供一个响应
public static void downLoad(String path, HttpServletResponse resp) { try { FileInputStream fileInputStream = new FileInputStream(new File(path)); // 输出流 ServletOutputStream outputStream = resp.getOutputStream(); IOUtils.copy(fileInputStream, outputStream); String name = path.substring(path.lastIndexOf("/") + 1); // 通知浏览器下载 文件名称 resp.setHeader("Content-Dispostion", "attachment;fileName=" + URLEncoder.encode(name, "UTF-8")); // 关流 fileInputStream.close(); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
如果你感觉搞成工具类还不过瘾,不妨给它做成jar包,也很简单,只需要在MyEclipse或者Eclipse中 export-java-jar 就可以啦,这样你的东西就可以很简单的让别人使用啦…
jar包如何使用?
第一步:根据表单封装Bean
比如表单中有字段 name password pic
那封装成的Bean就包含 name password pic这几个属性
private String name; private String password; private String pic;
- 1
- 2
- 3
- 4
第二步:使用jar包方法
//准备存储路径 String storagePath = getServletContext().getRealPath("WEB-INF/image"); //定义空对象 User user = new User(); //调用工具类方法 LoadUtils.upload(storagePath, req, user); //数据就封装好了 System.out.println(user.toString());
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9