您的位置:首页 > 编程语言 > Java开发

Java Web文件上传

2019-07-14 11:51 155 查看
原文链接:https://www.geek-share.com/detail/2655638000.html

参考资料:https://www.geek-share.com/detail/2631427760.html

一、问题描述

Java Web文件上传需要借助一些第三方库,常用的是借助Apache的包,有两个:

commons-fileupload

commons-io

 

二、前端代码示例

<form method="post" id="uploadApkForm" action="uploadapk"
enctype="multipart/form-data">
<p>
文件:<input name="apkFile" type="file" /> <!--有multiple属性时支持选中多个文件同时上传-->
</p>
<p>
版本:<input name="version" type="text" placeholder="请输入版本信息" />
</p>
</form>
注:

 enctype="multipart/form-data" 是必须的,表示这是个含文件的form表单;

 若type="file" 的 input标签含有 multiple 属性,则能够在弹出框中同时选中多个文件上传

 

三、后端代码示例

try {
// 判断enctype属性是否为multipart/form-data
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {// 不是文件上传,用传统方法获取数据
// String userId = request.getParameter("userId");等
return;
}

// 为multipart/form-data
int maxMemorySize = 1024 * 1000 * 50;// 50MB
int maxRequestSize = 1024 * 1000 * 100;// 100MB
String projAbsolutePath = request.getRealPath("");
String uploadRelativeDir = "upload/apk/";
String uploadTmpRelativeDir = uploadRelativeDir + "/tmp/";
File uploadDirObj = new File(projAbsolutePath + uploadRelativeDir);
if (!uploadDirObj.exists()) {
uploadDirObj.mkdirs();
}
File uploadTmpDirObj = new File(projAbsolutePath + uploadTmpRelativeDir);
if (!uploadTmpDirObj.exists()) {
uploadTmpDirObj.mkdirs();
}

// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();

// 当上传文件太大时,因为虚拟机能使用的内存是有限的,所以此时要通过临时文件来实现上传文件的保存
// 此方法是设置是否使用临时文件的临界值(单位:字节)
factory.setSizeThreshold(maxMemorySize);
// 与上一个结合使用,设置临时文件的路径(绝对路径)
factory.setRepository(uploadTmpDirObj);

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// 解决上传文件名的中文乱码,tomcat8不需要了
// upload.setHeaderEncoding("UTF-8");

// 设置上传内容的大小限制(单位:字节)
upload.setSizeMax(maxRequestSize);

// Parse the request
List<FileItem> items = upload.parseRequest(request);
Iterator<?> iter = items.iterator();
String fieldName = null;
FileItem item = null;
String fileName = null;
String version = null;
while (iter.hasNext()) {
item = (FileItem) iter.next();
fieldName = item.getFieldName();
if (item.isFormField()) {// 普通表单字段,版本信息
version = item.getString();
System.out.println(fieldName + " " + version);
} else {// 文件字段
fileName = item.getName();
if (!fileName.endsWith("apk")) {// 不是apk文件
System.out.println("不是apk文件");
return;
}
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
System.out.println(fileName + " " + contentType + " " + isInMemory + " " + sizeInBytes);
item.write(new File(uploadDirObj, fileName));
}
}
apkInfoMapper.insertVersionInfo(version,
new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(System.currentTimeMillis()),
(uploadRelativeDir + fileName));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
View Code

 注:

 为保证服务器安全,如果文件不提供下载,上传文件应该放在外界无法直接访问的目录下,如WEB-INF目录下;

 不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,而有些只是单纯的文件名,要处理获取到的上传文件的文件名的路径部分,只保留文件名部分;

 为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名

 四、扩展:利用SpringMVC实现单文件/多文件上传下载

1 package com.mucfc;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.net.URLEncoder;
9 import java.util.ArrayList;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.UUID;
15
16 import javax.servlet.ServletContext;
17 import javax.servlet.http.HttpServletRequest;
18 import javax.servlet.http.HttpServletResponse;
19
20 import org.springframework.stereotype.Controller;
21 import org.springframework.ui.ModelMap;
22 import org.springframework.web.bind.annotation.RequestMapping;
23 import org.springframework.web.bind.annotation.RequestParam;
24 import org.springframework.web.multipart.MultipartFile;
25 import org.springframework.web.multipart.MultipartHttpServletRequest;
26 import org.springframework.web.multipart.commons.CommonsMultipartFile;
27 import org.springframework.web.multipart.commons.CommonsMultipartResolver;
28
29 @Controller
30 @RequestMapping("/file")
31 public class FileController {
32
33     @RequestMapping("/toFile")
34     public String toFileUpload() {
35         return "fileUpload";
36     }
37
38     @RequestMapping("/toFile2")
39     public String toFileUpload2() {
40         return "fileUpload2";
41     }
42
43     /**
44      * 方法一上传文件
45      */
46     @RequestMapping("/onefile")
47     public String oneFileUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request,
48             ModelMap model) {
49
50         // 获得原始文件名
51         String fileName = file.getOriginalFilename();
52         System.out.println("原始文件名:" + fileName);
53
54         // 新文件名
55         String newFileName = UUID.randomUUID() + fileName;
56
57         // 获得项目的路径
58         ServletContext sc = request.getSession().getServletContext();
59         // 上传位置
60         String path = request.getRealPath("/img") + "/"; // 设定文件保存的目录
61
62         File f = new File(path);
63         if (!f.exists())
64             f.mkdirs();
65         if (!file.isEmpty()) {
66             try {
67                 FileOutputStream fos = new FileOutputStream(path + newFileName);
68                 InputStream in = file.getInputStream();
69                 int b = 0;
70                 while ((b = in.read()) != -1) {
71                     fos.write(b);
72                 }
73                 fos.close();
74                 in.close();
75             } catch (Exception e) {
76                 e.printStackTrace();
77             }
78         }
79
80         System.out.println("上传图片到:" + path + newFileName);
81         // 保存文件地址,用于JSP页面回显
82         model.addAttribute("fileUrl", "img/" + newFileName);
83         return "fileUpload";
84     }
85
86     /**
87      * 方法二上传文件,一次一张
88      */
89     @RequestMapping("/onefile2")
90     public String oneFileUpload2(HttpServletRequest request, HttpServletResponse response) throws Exception {
91         CommonsMultipartResolver cmr = new CommonsMultipartResolver(request.getServletContext());
92         if (cmr.isMultipart(request)) {
93             MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) (request);
94             Iterator<String> files = mRequest.getFileNames();
95             while (files.hasNext()) {
96                 MultipartFile mFile = mRequest.getFile(files.next());
97                 if (mFile != null) {
98                     String fileName = UUID.randomUUID() + mFile.getOriginalFilename();
99                     String path = request.getRealPath("") + "/img/" + fileName;
100                     System.out.println(path);
101                     File localFile = new File(path);
102                     if (!localFile.exists()) {
103                         localFile.createNewFile();
104                     }
105                     mFile.transferTo(localFile);
106                     request.setAttribute("fileUrl", "img/" + fileName);
107                 }
108             }
109         }
110         return "fileUpload";
111     }
112
113     /**
114      * 一次上传多张图片
115      */
116     @RequestMapping("/threeFile")
117     public String threeFileUpload(@RequestParam("file") CommonsMultipartFile files[], HttpServletRequest request,
118             ModelMap model) {
119
120         List<String> list = new ArrayList<String>();
121         // 获得项目的路径
122         ServletContext sc = request.getSession().getServletContext();
123         // 上传位置
124         String path = sc.getRealPath("/img") + "/"; // 设定文件保存的目录
125         File f = new File(path);
126         if (!f.exists())
127             f.mkdirs();
128
129         for (int i = 0; i < files.length; i++) {
130             // 获得原始文件名
131             String fileName = files[i].getOriginalFilename();
132             System.out.println("原始文件名:" + fileName);
133             // 新文件名
134             String newFileName = UUID.randomUUID() + fileName;
135             if (!files[i].isEmpty()) {
136                 try {
137                     FileOutputStream fos = new FileOutputStream(path + newFileName);
138                     InputStream in = files[i].getInputStream();
139                     int b = 0;
140                     while ((b = in.read()) != -1) {
141                         fos.write(b);
142                     }
143                     fos.close();
144                     in.close();
145                 } catch (Exception e) {
146                     e.printStackTrace();
147                 }
148             }
149             System.out.println("上传图片到:" + path + newFileName);
150             list.add("img/" + newFileName);
151
152         }
153         // 保存文件地址,用于JSP页面回显
154         model.addAttribute("fileList", list);
155         return "fileUpload2";
156
157     }
158
159     /**
160      * 列出所有的图片
161      */
162     @RequestMapping("/listFile")
163     public String listFile(HttpServletRequest request, HttpServletResponse response) {
164         // 获取上传文件的目录
165         ServletContext sc = request.getSession().getServletContext();
166         // 上传位置
167         String uploadFilePath = sc.getRealPath("/img") + "/"; // 设定文件保存的目录
168         // 存储要下载的文件名
169         Map<String, String> fileNameMap = new HashMap<String, String>();
170         // 递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中
171         listfile(new File(uploadFilePath), fileNameMap);// File既可以代表一个文件也可以代表一个目录
172         // 将Map集合发送到listfile.jsp页面进行显示
173         request.setAttribute("fileNameMap", fileNameMap);
174         return "listFile";
175     }
176
177     public void listfile(File file, Map<String, String> map) {
178         // 如果file代表的不是一个文件,而是一个目录
179         if (!file.isFile()) {
180             // 列出该目录下的所有文件和目录
181             File files[] = file.listFiles();
182             // 遍历files[]数组
183             for (File f : files) {
184                 // 递归
185                 listfile(f, map);
186             }
187         } else {
188             /**
189              * 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
190              * file.getName().indexOf
191              * ("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
192              * 那么file.getName().substring(file.getName().indexOf("_")+1)
193              * 处理之后就可以得到
194              */
195             String realName = file.getName().substring(file.getName().indexOf("_") + 1);
196             // file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
197             map.put(file.getName(), realName);
198         }
199     }
200
201     @RequestMapping("/downFile")
202     public void downFile(HttpServletRequest request, HttpServletResponse response) {
203         System.out.println("1");
204         // 得到要下载的文件名
205         String fileName = request.getParameter("filename");
206         System.out.println("2");
207         try {
208             fileName = new String(fileName.getBytes("iso8859-1"), "UTF-8");
209             System.out.println("3");
210             // 获取上传文件的目录
211             ServletContext sc = request.getSession().getServletContext();
212             System.out.println("4");
213             // 上传位置
214             String fileSaveRootPath = sc.getRealPath("/img");
215
216             System.out.println(fileSaveRootPath + "\\" + fileName);
217             // 得到要下载的文件
218             File file = new File(fileSaveRootPath + "\\" + fileName);
219
220             // 如果文件不存在
221             if (!file.exists()) {
222                 request.setAttribute("message", "您要下载的资源已被删除!!");
223                 System.out.println("您要下载的资源已被删除!!");
224                 return;
225             }
226             // 处理文件名
227             String realname = fileName.substring(fileName.indexOf("_") + 1);
228             // 设置响应头,控制浏览器下载该文件
229             response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
230             // 读取要下载的文件,保存到文件输入流
231             FileInputStream in = new FileInputStream(fileSaveRootPath + "\\" + fileName);
232             // 创建输出流
233             OutputStream out = response.getOutputStream();
234             // 创建缓冲区
235             byte buffer[] = new byte[1024];
236             int len = 0;
237             // 循环将输入流中的内容读取到缓冲区当中
238             while ((len = in.read(buffer)) > 0) {
239                 // 输出缓冲区的内容到浏览器,实现文件下载
240                 out.write(buffer, 0, len);
241             }
242             // 关闭文件输入流
243             in.close();
244             // 关闭输出流
245             out.close();
246         } catch (Exception e) {
247
248         }
249     }
250 }
View Code

 

原理:Servlet或Spring(实际上也是依赖Servlet)将收到的文件持久化到默认的临时磁盘目录(用户也可以指定),代码中获取到的File对象即是存在该临时目录的文件对象

 

转载于:https://www.cnblogs.com/z-sm/p/4872004.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: