需求描述:项目分成两块,客户端(CS架构)和管理平台(BS架构),客户端负责主要的业务功能并生成日志,管理平台对日志进行下载等操作。具体来说,客户端生成日志时会把日志路径等信息插入进数据库,管理平台可以选择将那些日志打包下载下来。
这里主要用到两部分知识,一个是客户端和管理平台的socket文件传输,一个是管理平台的文件下载
一、管理平台代码
js(点击按钮调用):
//此处使用ajax方式会无法弹出下载框function download() { ... //省略获取日志路径代码 var url = "http://127.0.0.1:8080/web/dsp/banklog/download.do"; var logPaths = pksArray.join(","); //将选择的日志路径以逗号相隔 var form = $("").attr("action", url).attr("method", "post"); form.append($("").attr("type", "hidden").attr("name", "logPaths").attr("value", logPaths)); form.appendTo('body').submit().remove();}
Controller:
下载的实现有两种方式(BaseReturnResult只是一个普通传输对象,自己实现时用map一样)
SpringMVC方式
@RequestMapping(value = "/download.do")public ResponseEntitydownload(@RequestParam("logPaths") String logPaths) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", "error.txt"); try { BaseReturnResult msgobject = bankLogService.download(logPaths); if (msgobject.getSuccess()) { //成功获取到文件后进行下载 String fileName = (String) msgobject.getExtraData(); File file = new File(fileName); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", file.getName()); //return new ResponseEntity (FileUtils.readFileToByteArray(file), // headers, // HttpStatus.CREATED); //IE不支持201,所以要改成200 return new ResponseEntity (FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); } } catch (Exception e) { e.printStackTrace(); return new ResponseEntity ("出现异常".getBytes(), headers, HttpStatus.OK); } return new ResponseEntity ("文件不存在".getBytes(), headers, HttpStatus.OK);}
Servlet方式
@RequestMapping(value = "/download.do")public ResponseEntitydownload(@RequestParam("logPaths") String logPaths, HttpServletResponse response) { try { BaseReturnResult msgobject = bankLogService.download(logPaths); if (msgobject.getSuccess()) { //成功获取到文件后进行下载 String fileName = (String) msgobject.getExtraData(); File file = new File(fileName); InputStream inputStream = new FileInputStream(fileName); OutputStream outputStream = response.getOutputStream(); response.setContentType("application/octet-stream"); response.addHeader("Content-Disposition", "attachment; filename=" + file.getName()); int temp = 0; while ((temp = inputStream.read()) != -1) { outputStream.write(temp); outputStream.flush(); } outputStream.close(); inputStream.close(); } } catch (Exception e) { e.printStackTrace(); }}
另外之前搜的众多资料里都说要在springmvc配置里加上如下配置,然而我去掉了发现也没有影响
text/plain;charset=UTF-8 text/html;charset=UTF-8
Service:
@Overridepublic BaseReturnResult download(String logPaths, SysUserDto userDto) { BaseReturnResult msgobject = BaseReturnResult.getFailResult(); Socket socket = null; DataOutputStream filePathOut = null; FileOutputStream downloadFileOut = null; DataInputStream downloadFileIn = null; try { //把要下载的日志路径传递给客户端 socket = new Socket("127.0.0.1", 6666); filePathOut = new DataOutputStream(socket.getOutputStream()); StringBuffer sb = new StringBuffer(); for(String logPath : logPaths.split(",")){ sb.append(logPath).append("\r\n"); } filePathOut.writeBytes(sb.toString()); filePathOut.flush(); socket.shutdownOutput(); //获取日志zip包 String fileName = System.getProperty("user.dir") + File.separator + System.currentTimeMillis() + ".zip"; downloadFileOut = new FileOutputStream(fileName); downloadFileIn = new DataInputStream(socket.getInputStream()); int temp = 0; while((temp = downloadFileIn.read()) != -1){ downloadFileOut.write(temp); } downloadFileOut.flush(); msgobject.setExtraData(fileName); } catch (Exception e) { e.printStackTrace(); } finally { if(downloadFileOut != null){ try { downloadFileOut.close(); } catch (Exception e) {} } if(downloadFileIn != null){ try { downloadFileIn.close(); } catch (Exception e) {} } if(filePathOut != null){ try { filePathOut.close(); } catch (Exception e) {} } if(socket != null){ try { socket.close(); } catch (Exception e) {} } } return msgobject;}
二、客户端代码
public class BankLogSocketListener implements Runnable { private int listenPort = 0; public BankLogSocketListener(int listenPort) { this.listenPort = listenPort; } @Override public void run() { try { ServerSocket socketServer = new ServerSocket(listenPort, 500); while (true) { Socket socket = socketServer.accept(); System.out.println("接收到文件下载请求"); BankLogTransfer logTransfer = new BankLogTransfer(socket); new Thread(logTransfer).start(); } } catch (Exception e) { e.printStackTrace(); } } class BankLogTransfer implements Runnable { private Socket socket; BankLogTransfer(Socket socket) { this.socket = socket; } @Override public void run() { String zipName = System.currentTimeMillis() + ".zip"; try { ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zipName)); Scanner input = new Scanner(socket.getInputStream()); while (input.hasNextLine()) { String fileName = input.nextLine(); FileInputStream fileInput = new FileInputStream(FGBiz.dspCenter.bankLogsDirPath + File.separator + fileName); ZipEntry zipEntry = new ZipEntry(fileName); zout.putNextEntry(zipEntry); int temp = 0; while ((temp = fileInput.read()) != -1) { zout.write(temp); } zout.closeEntry(); fileInput.close(); } System.out.println("请求处理完毕"); socket.shutdownInput(); DataOutputStream out = new DataOutputStream(socket.getOutputStream()); FileInputStream fileInput = new FileInputStream(zipName); int temp = 0; while ((temp = fileInput.read()) != -1) { out.write(temp); } fileInput.close(); out.close(); input.close(); zout.close(); } catch (Exception ex) { ex.printStackTrace(); } } }}
在启动项目的时候启动监听:
new Thread(new BankLogSocketListener(6666)).start();