web項目的文件打包下載實現;servlet接收請求,spring工具類訪問數據庫及簡化大字段內容獲取,org.apache.tools.zip打包。html
必要提醒:當前總結是繼Java實現下載BLOB字段中的文件以後的總結,若有不解之處,請參考之。java
jdk提供了java.util.zip包,用於實現文件打包的功能,可是對中文名的文件沒有很好的支持。org.apache.tools.zip包提供了幾乎相同的接口,且額外提供了設置編碼的接口。web
1 public void write(OutputStream os, List fileList) throws IOException { 2 org.apache.tools.zip.ZipOutputStream zos 3 = new org.apache.tools.zip.ZipOutputStream(os); 4 zos.setEncoding(System.getProperty("sun.jnu.encoding")); 5 6 byte[] buff = new byte[1024]; 7 for (int i = 0; i < fileList.size(); i++) { 8 cn.com.hnisi.fzyw.xzfy.gz.download.domain.File file = 9 (cn.com.hnisi.fzyw.xzfy.gz.download.domain.File) fileList.get(i); 10 String name = "file" + (i + 1) + "_" + file.getName(); 11 InputStream content = file.getIs(); 12 13 zos.putNextEntry(new org.apache.tools.zip.ZipEntry(name)); 14 for (int len = content.read(buff); len > 0;) { 15 zos.write(buff, 0, len); 16 len = content.read(buff); 17 } 18 19 content.close(); 20 zos.closeEntry(); 21 } 22 23 zos.close(); 24 }
上述代碼實現了打包輸出的功能:將指定的文件列表打包以後寫到到指定的輸出流。spring
各類包的做用與Java實現下載BLOB字段中的文件中相同。sql
參考Java實現下載BLOB字段中的文件,沒有變化。數據庫
參考Java實現下載BLOB字段中的文件,沒有變化。apache
組件所包含的服務接口和實現類,添加了獲取批量數據的相關方法;同時爲了不代碼重複,原有方法的實現也稍有調整:dom
1 package cn.com.hnisi.fzyw.xzfy.gz.download.service; 2 import java.util.List; 3 import cn.com.hnisi.fzyw.xzfy.gz.download.domain.File; 4 public interface IDownloadService { 5 /** 6 * 讀取文件.<br> 7 * 8 * @param sql 9 * 查詢sql語句,必須包含文件名字段和文件內容字段. 10 * @param args 11 * 參數 - 確保sql查詢的結果只有一條. 12 * @param colNameFileName 13 * 存放文件名的字段名,大寫. 14 * @param colNameFileContent 15 * 存放文件內容的字段名,大寫. 16 * @return 17 */ 18 public File read(final String sql, final Object[] args, 19 final String colNameFileName, final String colNameFileContent); 20 21 /** 22 * SINOBEST 文件下載 批量讀取文件以供打包下載. 23 * @param sql 24 * @param colNameFileName 25 * @param colNameFileContent 26 * @return 27 */ 28 public List batchRead(final String sql, final String colNameFileName, 29 final String colNameFileContent); 30 }
1 package cn.com.hnisi.fzyw.xzfy.gz.download.service; 2 import java.io.IOException; 3 import java.sql.ResultSet; 4 import java.sql.SQLException; 5 import java.util.ArrayList; 6 import java.util.List; 7 import org.springframework.dao.DataAccessException; 8 import org.springframework.jdbc.core.JdbcTemplate; 9 import org.springframework.jdbc.core.support.AbstractLobStreamingResultSetExtractor; 10 import org.springframework.jdbc.support.lob.DefaultLobHandler; 11 import org.springframework.jdbc.support.lob.LobHandler; 12 import cn.com.hnisi.baseservices.db.JdbcTemplateFactory; 13 import cn.com.hnisi.fzyw.xzfy.gz.download.domain.File; 14 public class DownloadServiceImpl implements IDownloadService { 15 /** 16 * SINOBEST common 文件下載實現. 17 */ 18 public File read(final String sql, final Object[] args, 19 final String colNameFileName, final String colNameFileContent) { 20 String sql1 = sql.replaceFirst("\\?", "'"+(String)args[0]+"'"); 21 List fileList = batchRead(sql1, colNameFileName, colNameFileContent); 22 File file = (File)fileList.get(0); 23 return file; 24 } 25 26 /** 27 * SINOBEST 批量讀取BLOB類型數據 28 */ 29 public List batchRead(String sql, final String colNameFileName, 30 final String colNameFileContent) { 31 JdbcTemplate jt = JdbcTemplateFactory.newInstance().getDefaultJT(); 32 33 final LobHandler lobHandler = new DefaultLobHandler(); 34 35 final List listFile = new ArrayList(); 36 jt.query(sql, new AbstractLobStreamingResultSetExtractor() { 37 protected void streamData(ResultSet rs) throws SQLException, 38 IOException, DataAccessException { 39 do{ //SINOBEST 文件下載 ,此處的rs初始化時已經指向第一條記錄 40 File file = new File(); 41 file.setName(rs.getString(colNameFileName)); 42 file.setIs(lobHandler.getBlobAsBinaryStream(rs, 43 colNameFileContent)); 44 listFile.add(file); 45 }while(rs.next()); 46 } 47 }); 48 return listFile; 49 } 50 51 }
參考Java實現下載BLOB字段中的文件,沒有變化。ide
這是一個新的組件,用以打包、輸出到指定的輸出流。工具
打包服務的接口。
1 package cn.com.hnisi.fzyw.xzfy.gz.download.service; 2 import java.io.IOException; 3 import java.io.OutputStream; 4 import java.util.List; 5 /** 6 * SINONBEST 文件打包接口. 7 * 8 * @author lijinlong 9 * 10 */ 11 public interface IZipService { 12 /** 13 * SINOBEST 文件打包 將指定的多個文件打包成一個壓縮文件,輸出到指定的輸出流.<br> 14 * 15 * @param os 16 * 指定的輸出流 17 * @param fileList 18 * 指定的文件列表,每一個元素都包含了文件名和輸入流格式的文件內容 19 */ 20 public void write(OutputStream os, List fileList) throws IOException; 21 /** 22 * SINOBEST 文件打包 將數據庫中查詢到的多個文件壓縮以後輸出到指定的輸出流.<br> 23 * 24 * @param sql 文件查詢語句,包括文件名、文件內容(BLOB)兩個字段. 25 * @param colNameFileName 存放文件名的字段名. 26 * @param colNameFileContent 存放文件內容的字段名. 27 * @param os 指定的輸出流. 28 */ 29 public void write(final String sql, final String colNameFileName, 30 final String colNameFileContent, final OutputStream os) throws IOException; 31 }
打包服務實現類。
1 package cn.com.hnisi.fzyw.xzfy.gz.download.service; 2 import java.io.IOException; 3 import java.io.InputStream; 4 import java.io.OutputStream; 5 import java.util.List; 6 public class ZipServiceImpl implements IZipService { 7 public void write(OutputStream os, List fileList) throws IOException { 8 // 使用java.util.zip不支持設置編碼格式 9 org.apache.tools.zip.ZipOutputStream zos 10 = new org.apache.tools.zip.ZipOutputStream(os); 11 zos.setEncoding(System.getProperty("sun.jnu.encoding")); 12 byte[] buff = new byte[1024]; 13 for (int i = 0; i < fileList.size(); i++) { 14 cn.com.hnisi.fzyw.xzfy.gz.download.domain.File file = 15 (cn.com.hnisi.fzyw.xzfy.gz.download.domain.File) fileList.get(i); 16 String name = "file" + (i + 1) + "_" + file.getName(); 17 InputStream content = file.getIs(); 18 zos.putNextEntry(new org.apache.tools.zip.ZipEntry(name)); 19 for (int len = content.read(buff); len > 0;) { 20 zos.write(buff, 0, len); 21 len = content.read(buff); 22 } 23 content.close(); 24 zos.closeEntry(); 25 } 26 zos.close(); 27 } 28 public void write(String sql, String colNameFileName, 29 String colNameFileContent, OutputStream os) throws IOException { 30 IDownloadService ids = DownloadServiceFactory.newInstance() 31 .createDownloadService(); 32 List fileList = ids.batchRead(sql, colNameFileName, colNameFileContent); 33 write(os, fileList); 34 } 35 }
1 package cn.com.hnisi.fzyw.xzfy.gz.download.service; 2 public class ZipServiceFactory { 3 private static ZipServiceFactory instance; 4 private ZipServiceFactory() { 5 6 } 7 8 public static final synchronized ZipServiceFactory newInstance() { 9 if (instance == null) 10 instance = new ZipServiceFactory(); 11 12 return instance; 13 } 14 15 public IZipService create() { 16 IZipService service = new ZipServiceImpl(); 17 return service; 18 } 19 }
1 package cn.com.hnisi.fzyw.xzfy.gz.test.servlet; 2 import java.io.IOException; 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import cn.com.hnisi.fzyw.xzfy.gz.download.service.IZipService; 8 import cn.com.hnisi.fzyw.xzfy.gz.download.service.ZipServiceFactory; 9 public class BatchDownloadFileServlet extends HttpServlet { 10 private static final long serialVersionUID = -1288924386578872984L; 11 12 /** 13 * SINOBEST 文件打包下載 測試servlet.<br> 14 */ 15 public void service(HttpServletRequest request, HttpServletResponse response) 16 throws ServletException, IOException { 17 /* 1. 設置響應內容類型 */ 18 response.setContentType("Application/Octet-stream;charset=utf-8"); 19 20 /* 2. 將文件名加入響應頭 */ 21 String zipName = "打包下載" + System.currentTimeMillis() + ".zip"; 22 zipName = new String(zipName.getBytes(), "ISO-8859-1"); 23 response.addHeader("Content-Disposition", 24 "attachment; filename=" + zipName); 25 26 /* 3. 輸出文件內容 */ 27 String systemids = request.getParameter("systemids"); // systemids是多個systemid以逗號分隔拼接而成的字符序列 28 systemids = ("'" + systemids + "'").replaceAll(",", "','"); 29 String sql = "select CLMC, SQCL from V_FZYWGZ_JK_XZFYSQXX_CL where SYSTEMID in (?)" 30 .replaceFirst("\\?", systemids); 31 String colNameFileName = "CLMC"; 32 String colNameFileContent = "SQCL"; 33 IZipService service = ZipServiceFactory.newInstance().create(); 34 service.write(sql, colNameFileName, colNameFileContent, response.getOutputStream()); 35 36 /* 4. 關閉流 */ 37 response.getOutputStream().flush(); 38 response.getOutputStream().close(); 39 } 40 }