概述
web项目的文件打包下载实现;servlet接收请求,spring工具类访问数据库及简化大字段内容获取,org.apache.tools.zip打包。
必要提醒:当前总结是继Java实现下载BLOB字段中的文件之后的总结,如有不解之处,请参考之。
核心代码
jdk提供了java.util.zip包,用于实现文件打包的功能,但是对中文名的文件没有很好的支持。org.apache.tools.zip包提供了几乎相同的接口,且额外提供了设置编码的接口。
1 public void write(OutputStream os, List fileList) throwsIOException {2 org.apache.tools.zip.ZipOutputStream zos3 = neworg.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(neworg.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 }
核心代码
上述代码实现了打包输出的功能:将指定的文件列表打包之后写到到指定的输出流。
代码优化
包图
类图
数据库访问支持组件
File
数据库访问组件
组件所包含的服务接口和实现类,添加了获取批量数据的相关方法;同时为了避免代码重复,原有方法的实现也稍有调整:
IDownloadService
1 packagecn.com.hnisi.fzyw.xzfy.gz.download.service;2 importjava.util.List;3 importcn.com.hnisi.fzyw.xzfy.gz.download.domain.File;4 public interfaceIDownloadService {5 /**
6 * 读取文件.
7 *8 *@paramsql9 * 查询sql语句,必须包含文件名字段和文件内容字段.10 *@paramargs11 * 参数 - 确保sql查询的结果只有一条.12 *@paramcolNameFileName13 * 存放文件名的字段名,大写.14 *@paramcolNameFileContent15 * 存放文件内容的字段名,大写.16 *@return
17 */
18 public File read(final String sql, finalObject[] args,19 final String colNameFileName, finalString colNameFileContent);20
21 /**
22 * SINOBEST 文件下载 批量读取文件以供打包下载.23 *@paramsql24 *@paramcolNameFileName25 *@paramcolNameFileContent26 *@return
27 */
28 public List batchRead(final String sql, finalString colNameFileName,29 finalString colNameFileContent);30 }
IDownloadService
DownloadServiceImpl
1 packagecn.com.hnisi.fzyw.xzfy.gz.download.service;2 importjava.io.IOException;3 importjava.sql.ResultSet;4 importjava.sql.SQLException;5 importjava.util.ArrayList;6 importjava.util.List;7 importorg.springframework.dao.DataAccessException;8 importorg.springframework.jdbc.core.JdbcTemplate;9 importorg.springframework.jdbc.core.support.AbstractLobStreamingResultSetExtractor;10 importorg.springframework.jdbc.support.lob.DefaultLobHandler;11 importorg.springframework.jdbc.support.lob.LobHandler;12 importcn.com.hnisi.baseservices.db.JdbcTemplateFactory;13 importcn.com.hnisi.fzyw.xzfy.gz.download.domain.File;14 public class DownloadServiceImpl implementsIDownloadService {15 /**
16 * SINOBEST common 文件下载实现.17 */
18 public File read(final String sql, finalObject[] args,19 final String colNameFileName, finalString colNameFileContent) {20 String sql1 = sql.replaceFirst("\\?", "'"+(String)args[0]+"'");21 List fileList =batchRead(sql1, colNameFileName, colNameFileContent);22 File file = (File)fileList.get(0);23 returnfile;24 }25
26 /**
27 * SINOBEST 批量读取BLOB类型数据28 */
29 public List batchRead(String sql, finalString colNameFileName,30 finalString colNameFileContent) {31 JdbcTemplate jt =JdbcTemplateFactory.newInstance().getDefaultJT();32
33 final LobHandler lobHandler = newDefaultLobHandler();34
35 final List listFile = newArrayList();36 jt.query(sql, newAbstractLobStreamingResultSetExtractor() {37 protected void streamData(ResultSet rs) throwsSQLException,38 IOException, DataAccessException {39 do{ //SINOBEST 文件下载 ,此处的rs初始化时已经指向第一条记录
40 File file = newFile();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 returnlistFile;49 }50
51 }
DownloadServiceImpl
DownloadServiceFactory
打包输出组件
这是一个新的组件,用以打包、输出到指定的输出流。
IZipService
打包服务的接口。
1 packagecn.com.hnisi.fzyw.xzfy.gz.download.service;2 importjava.io.IOException;3 importjava.io.OutputStream;4 importjava.util.List;5 /**
6 * SINONBEST 文件打包接口.7 *8 *@authorlijinlong9 *10 */
11 public interfaceIZipService {12 /**
13 * SINOBEST 文件打包 将指定的多个文件打包成一个压缩文件,输出到指定的输出流.
14 *15 *@paramos16 * 指定的输出流17 *@paramfileList18 * 指定的文件列表,每个元素都包含了文件名和输入流格式的文件内容19 */
20 public void write(OutputStream os, List fileList) throwsIOException;21 /**
22 * SINOBEST 文件打包 将数据库中查询到的多个文件压缩之后输出到指定的输出流.
23 *24 *@paramsql 文件查询语句,包括文件名、文件内容(BLOB)两个字段.25 *@paramcolNameFileName 存放文件名的字段名.26 *@paramcolNameFileContent 存放文件内容的字段名.27 *@paramos 指定的输出流.28 */
29 public void write(final String sql, finalString colNameFileName,30 final String colNameFileContent, final OutputStream os) throwsIOException;31 }
IZipService
ZipServiceImpl
打包服务实现类。
1 packagecn.com.hnisi.fzyw.xzfy.gz.download.service;2 importjava.io.IOException;3 importjava.io.InputStream;4 importjava.io.OutputStream;5 importjava.util.List;6 public class ZipServiceImpl implementsIZipService {7 public void write(OutputStream os, List fileList) throwsIOException {8 //使用java.util.zip不支持设置编码格式
9 org.apache.tools.zip.ZipOutputStream zos10 = neworg.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(neworg.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 voidwrite(String sql, String colNameFileName,29 String colNameFileContent, OutputStream os) throwsIOException {30 IDownloadService ids =DownloadServiceFactory.newInstance()31 .createDownloadService();32 List fileList =ids.batchRead(sql, colNameFileName, colNameFileContent);33 write(os, fileList);34 }35 }
ZipServiceImpl
ZipServiceFactory
1 packagecn.com.hnisi.fzyw.xzfy.gz.download.service;2 public classZipServiceFactory {3 private staticZipServiceFactory instance;4 privateZipServiceFactory() {5
6 }7
8 public static final synchronizedZipServiceFactory newInstance() {9 if (instance == null)10 instance = newZipServiceFactory();11
12 returninstance;13 }14
15 publicIZipService create() {16 IZipService service = newZipServiceImpl();17 returnservice;18 }19 }
ZipServiceFactory
Servlet
BatchDownloadFileServlet
1 packagecn.com.hnisi.fzyw.xzfy.gz.test.servlet;2 importjava.io.IOException;3 importjavax.servlet.ServletException;4 importjavax.servlet.http.HttpServlet;5 importjavax.servlet.http.HttpServletRequest;6 importjavax.servlet.http.HttpServletResponse;7 importcn.com.hnisi.fzyw.xzfy.gz.download.service.IZipService;8 importcn.com.hnisi.fzyw.xzfy.gz.download.service.ZipServiceFactory;9 public class BatchDownloadFileServlet extendsHttpServlet {10 private static final long serialVersionUID = -1288924386578872984L;11
12 /**
13 * SINOBEST 文件打包下载 测试servlet.
14 */
15 public voidservice(HttpServletRequest request, HttpServletResponse response)16 throwsServletException, 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 }
BatchDownloadFileServlet