項目里一直有這個功能,也一直沒怎么注意,今天研究了一下
依據邏輯往下走:
首先是要下載的ajax的Java方法,只有返回值需要設定一下,其他的不用管:
Map<String, Object> resultMap = pdfService.createPDF(dest,jsonObject); //文件保存路徑,不包含文件名,例:d:\\aaa\\uploadFileRoot\\ resultMap.put("filePath", savePath); //文件名 resultMap.put("fileName", fileName); return JSON.toJSONString(resultMap);
然后前端接收返回值:
res = JSON.stringify(res) var data = JSON.parse(res); // 本地 將路徑中的\\用字母z代替,需要注意,如果下面open里的方法有z就需要換字母,換成沒有的,不然后面解析會出錯 var a = data.filePath.replace(/\\/g, "z"); // 發布 // var a = data1.a.replace(/\//g, "z"); window .open("/pdf/downLoadTemp.do?a=" + a + "&b=" + data.fileName);
把這個代碼單獨放到一個方法中方便重用(如果中間文件不需要保存,可以在finally中刪除這個文件):
@RequestMapping("downLoadTemp.do") public void downLoadTemp(HttpServletRequest req,HttpServletResponse res,String a,String b) throws Exception { String filePath = a.replace("z", downLoadTemp);// downLoadTemp如果項目在本地是\\,服務器是/ String fileName = b;// 保存窗口中顯示的文件名 res.setContentType("APPLICATION/OCTET-STREAM"); /* * 要顯示到客戶端的文件名轉碼是必需的,特別是中文名 否則可能出現文件名亂碼甚至是瀏覽器顯示無法下載的問題 */ ServletOutputStream out = null; // PrintWriter out = null; InputStream inStream = null; try { fileName = res.encodeURL(new String(fileName.getBytes("UTF-8"), "ISO8859_1"));// res.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // inline out = res.getOutputStream(); System.out.println( filePath + toUtf8String(fileName) + ".........................................................."); inStream = new FileInputStream(filePath + toUtf8String(fileName)); // 下載需要加密 // DrmEdiClient.getInstance().encryptAuthFile(inStream,out, // ?,?,?); // 循環取出流中的數據 byte[] by = new byte[1024]; int len; while ((len = inStream.read(by)) > 0) out.write(by, 0, len); res.setStatus(res.SC_OK); res.flushBuffer(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (RuntimeException e) { e.printStackTrace(); } finally { if (out != null) out.close(); inStream.close(); } }
既然寫了這方面的,那就把多個文件打包下載也寫了把:(fileInfo為我們公司的存儲文件屬性的類),這是我之前寫的代碼了,過去好久都忘了
if (list != null && list.size() > 0) { Map<String, String> temp = new HashMap<String, String>(); //要下載的文件的集合 File[] fileArray = new File[list.size()]; Map<String, String> newName = new HashMap<String, String>(); for (int i = 0; i < list.size(); i++) { FileInfo fi = list.get(i); String deskName = new File(fi.getFilePath()).getName(); String fileName = fi.getFileName(); String fn = temp.get(fileName); if (fn != null) {// 打包下載版本文件保證文件不同名 String uploadDate = DateUtil.format(fi.getUploadTime(), "yyyyMMddHHmmss"); fileName = uploadDate + fileName; if (i == 1) { FileInfo _fi = list.get(0); String _deskName = new File(_fi.getFilePath()) .getName(); String _fileName = _fi.getFileName(); String _uploadDate = DateUtil.format( _fi.getUploadTime(), "yyyyMMddHHmmss"); _fileName = _uploadDate + _fileName; newName.put(_deskName, _fileName); } } temp.put(fileName, ""); newName.put(deskName, fileName); File f = new File(fi.getFilePath()); fileArray[i] = f; } File zipFile = new File(new Date().getTime() + ".zip"); //ZipUtil為公司封裝的zip下載工具類 ZipUtil.zip(fileArray, zipFile, newName); String pathSaveFile = zipFile.getAbsolutePath();// 要下載的文件 String fileName = "files.zip";// 保存窗口中顯示的文件名 super.getResponse().reset(); super.getResponse().setContentType("APPLICATION/OCTET-STREAM"); /* * 要顯示到客戶端的文件名轉碼是必需的,特別是中文名 否則可能出現文件名亂碼甚至是瀏覽器顯示無法下載的問題 */ ServletOutputStream out = null; InputStream inStream = null; try { fileName = super.getResponse().encodeURL( new String(fileName.getBytes("GBK"), "ISO8859_1"));// super.getResponse().setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // inline out = super.getResponse().getOutputStream(); inStream = new FileInputStream(pathSaveFile); // 循環取出流中的數據 byte[] b = new byte[1024]; int len; while ((len = inStream.read(b)) > 0) out.write(b, 0, len); super.getResponse().setStatus(super.getResponse().SC_OK); super.getResponse().flushBuffer(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) out.close(); if (inStream != null) inStream.close(); zipFile.delete(); } }
ZipUtil.zip的方法:
public static void zip(File[] files, File out, Map<String, String> newName) { if (files != null) { Map<String, File> map = new HashMap(); for (File f : files) { list(f, null, map); } if (!map.isEmpty()) { try { ZipArchiveOutputStream zaos = new ZipArchiveOutputStream(out); for (Map.Entry<String, File> entry : map.entrySet()) { File file = (File)entry.getValue(); String name = null; if ((newName != null) && (newName.size() > 0)) { String deskName = file.getName(); name = (String)newName.get(deskName); } name = name == null ? (String)entry.getKey() : name; ZipArchiveEntry zae = new ZipArchiveEntry(file, name); zaos.putArchiveEntry(zae); InputStream is = new FileInputStream(file); byte[] b = new byte['?']; int i = -1; while ((i = is.read(b)) != -1) { zaos.write(b, 0, i); } is.close(); zaos.closeArchiveEntry(); } zaos.finish(); zaos.close(); } catch (IOException ex) { log.error(ex.getMessage(), ex); } } } }
public static String toUtf8String(String s) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c >= 0 && c <= 255) { sb.append(c); } else { byte[] b; try { b = Character.toString(c).getBytes("utf-8"); } catch (Exception ex) { System.out.println(ex); b = new byte[0]; } for (int j = 0; j < b.length; j++) { int k = b[j]; if (k < 0) k += 256; sb.append("%" + Integer.toHexString(k).toUpperCase()); } } } return sb.toString(); }