在文件上传和下载(可批量上传)——Spring(二)的基础上,发现了文件下载时,只有在Chrome浏览器下文件名正常显示,还有发布到服务器后,不能上传到指定的文件夹目录,如上传20160310.txt文件,上传到正是服务器后,并没有在upload文件夹下,而是以upload/20160310.txt这样的文加名的文件。针对以上问题,进行了修正。最后一个错误是,在显示文件列表的时候如果对应项目下没有文件夹会报空指针异常。
处理空指针异常的。
处理文件名中文显示正常和处理无法上传到正确的文件夹
完整代码如下
1 package com.tommy.business;
2
3 import org.apache.commons.fileupload.FileItem;
4 import org.apache.commons.fileupload.FileUploadException;
5 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
6 import org.apache.commons.fileupload.servlet.ServletFileUpload;
7 import org.springframework.stereotype.Controller;
8 import org.springframework.web.bind.annotation.RequestMapping;
9 import org.springframework.web.multipart.MultipartFile;
10 import org.springframework.web.multipart.MultipartHttpServletRequest;
11 import org.springframework.web.multipart.commons.CommonsMultipartFile;
12 import org.springframework.web.multipart.commons.CommonsMultipartResolver;
13
14 import javax.servlet.ServletException;
15 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpServletResponse;
17 import java.io.*;
18 import java.net.URLEncoder;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 /**
24 * Created by OnlyOne on 2016/3/4.
25 */
26 @Controller
27 @RequestMapping("/background/uploadAndDownload/")
28 public class UploadAndDownloadController {
29 /**
30 *
31 * @param req
32 * @param resp
33 * @throws ServletException
34 * @throws IOException
35 * @throws FileUploadException
36 */
37 @RequestMapping("uploadFile")
38 public String uploadFile(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, FileUploadException {
39 /*//防止中文乱码,与页面字符集一致
40 req.setCharacterEncoding("UTF-8");*/
41 //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
42 String savePath = req.getServletContext().getRealPath("/upload");
43 // this.getServletContext().getRealPath("/WEB-INF/upload");
44 //创建保存目录的文件
45 File saveFile = new File(savePath);
46 //判断保存目录文件是否存在,不存在则创建一个文件夹
47 if(!saveFile.exists()){
48 System.out.println("文件目录创建中。。。");
49 saveFile.mkdir();
50 }
51 //消息提示
52 //将req转换成Spring的request
53 MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) req;
54 //获取上传文件
55 List<MultipartFile> list = multipartHttpServletRequest.getFiles("file");
56 /*//获取普通输入项的数据
57 String map = multipartHttpServletRequest.getParameter("username");
58 System.out.println(map);*/
59 for(MultipartFile multipartFile: list){
60 if(!multipartFile.isEmpty()){
61 //得到上传的文件名称
62 String fileName = multipartFile.getOriginalFilename();
63 System.out.println("文件名是:"+ fileName);
64 if(fileName == null || fileName.trim().equals("")){
65 continue;
66 }
67 //获取item中的上传输入流
68 BufferedInputStream bis = new BufferedInputStream(multipartFile.getInputStream());
69 //创建一个文件输出流
70 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(savePath + "/" + fileName));
71 //创建一个缓冲区
72 byte[] buffer = new byte[1024*8];
73 //循环将缓冲输入流读入到缓冲区当中
74 while(true){
75 //循环将缓冲输入流读入到缓冲区当中
76 int length = bis.read(buffer);
77 //判断是否读取到文件末尾
78 if(length == -1){
79 break;
80 }
81 //使用BufferedOutputStream缓冲输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
82 bos.write(buffer,0,length);
83 }
84 //关闭输入流
85 bis.close();
86 //关闭输出流
87 bos.close();
88 }
89 }
90 return "redirect:listFile.html";
91 }
92
93 /**
94 * @ClassName: ListFileServlet
95 * @Description: 列出Web系统中所有下载文件
96 * @param req
97 * @param resp
98 */
99 @RequestMapping("listFile")
100 public String listFile(HttpServletRequest req, HttpServletResponse resp) {
101 String flag = req.getParameter("flag");
102 //获取上传文件的目录
103 String uploadFilePath = req.getServletContext().getRealPath("/upload");
104 //创建保存目录的文件
105 File saveFile = new File(uploadFilePath);
106 //判断保存目录文件是否存在,不存在则创建一个文件夹
107 if(!saveFile.exists()){
108 System.out.println("文件目录创建中。。。");
109 saveFile.mkdir();
110 }
111 //存储要下载的文件名
112 Map<String, String> fileNameMap = new HashMap<String, String>();
113 //地鬼遍历filePath目录下的所有文件和目录,将文件的文件名存储到map集合中
114 getListfile(new File(uploadFilePath), fileNameMap);
115 if(flag != null){
116 req.setAttribute("flag",flag);
117 }
118 req.setAttribute("fileNameMap", fileNameMap);
119 return "/background/uploadAndDownload/resourcesList";
120 }
121
122 /**
123 *
124 * @param file 即代表一个文件,也代表一个文件目录
125 * @param map 存储文件名的Map集合
126 * @Method: listfile
127 * @Description: 递归遍历指定目录下的所有文件
128 */
129 private void getListfile(File file, Map<String, String> map) {
130 //如果file代表的不是一个文件,而是一个目录
131 if (!file.isFile()) {
132 //列出该目录下的所有文件和目录
133 File files[] = file.listFiles();
134 //遍历files[]数组
135 for (File f : files) {
136 //递归
137 getListfile(f, map);
138 }
139 } else {
140 /**
141 * 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
142 file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
143 那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分
144 */
145 //String realName = file.getName().substring(file.getName().indexOf("_") + 1);
146 //file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
147 map.put(file.getName(), file.getName());
148 }
149 }
150
151 /**
152 * 下载文件
153 * @param req
154 * @param resp
155 * @throws ServletException
156 * @throws IOException
157 */
158 @RequestMapping("downLoadFile")
159 public void downLoadFile(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
160 /*//得到要下载的文件名
161 req.setCharacterEncoding("UTF-8");*/
162 String fileName = req.getParameter("fileName");
163 // fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
164 //上传的文件都是保存在/WEN-INF/upload目录党徽宗
165 String fileSavePath = req.getServletContext().getRealPath("/upload");
166 //得到要下载的文件
167 File file = new File(fileSavePath + "//" + fileName);
168 //如果文件不存在
169 if(!file.exists()){
170 req.setAttribute("message", "资源已被删除!");
171 req.getRequestDispatcher("/message.jsp").forward(req, resp);
172 }
173 //处理文件名
174 String realName = fileName.substring(fileName.indexOf("_")+1);
175 String agent = req.getHeader("user-agent");
176 resp.setContentType("application/x-download");
177 //处理下载时文件名乱码,针对不同浏览器做处理
178 if(agent.contains("Firefox")){
179 realName = new String(realName.getBytes("GB2312"),"ISO-8859-1");
180 //resp.addHeader("Content-Disposition","attachment;filename="+ new String(realName.getBytes("GB2312"),"ISO-8859-1"));
181 }else {
182 realName = URLEncoder.encode(realName, "UTF-8");
183 //resp.addHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(realName, "UTF-8"));
184 }
185 //设置响应头,控制浏览器下载该文件
186 resp.setHeader("content-disposition", "attachment;filename="+realName);
187 //读取要下载的文件,保存到文件输入流
188 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileSavePath + "/" + fileName));
189 //以前的写法,本地可以,发布到服务器后就不能上传到指定的文件夹而是已upload\***的形式作为文件名,应该是转义符"\\"在linux转义的不是"/"
190 // BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileSavePath + "\\" + fileName));
191 //创建输出流
192 BufferedOutputStream bos = new BufferedOutputStream(resp.getOutputStream());
193 //创建一个缓冲区
194 byte[] buffer = new byte[1024*8];
195 //循环将缓冲输入流读入到缓冲区当中
196 while(true){
197 //循环将缓冲输入流读入到缓冲区当中
198 int length = bis.read(buffer);
199 //判断是否读取到文件末尾
200 if(length == -1){
201 break;
202 }
203 //使用BufferedOutputStream缓冲输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
204 bos.write(buffer,0,length);
205 }
206 //关闭文件输入流
207 bis.close();
208 //刷新此输入流并强制写出所有缓冲的输出字节数
209 bos.flush();
210 //关闭文件输出流
211 bos.close();
212 }
213
214 }