文件上传和下载(可批量上传)——Spring(三)
在文件上传和下载(可批量上传)——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 }
What a meaningless sense if losing myself,though owning all of the world.