zoukankan      html  css  js  c++  java
  • POI导出时写一份到ftp服务器,一份下载给客户端

    导语:

      昨天接到项目经理这么一个需求,让我在POI导出Excel的时候写一份到我之前搭建的ftp服务器上。所以就有了这篇博客首先我们来分析下之前的业务逻辑:我们创建并构造了一个workbook,然后构建了一个OutputStream输出流,然后我们把数据写入输出流中就可以被客户端下载。

      现在我们要在此基础上写一份到ftp服务器

      那么我们就需要两个流,首先一个输入流把文件写到ftp服务器,然后需要一个输出流把文件输出到客户端。千万不要用workbook.write(out)一份到客户端,然后又workbook.write(in)一份到ftp,会报错的。Stream is closed,(为啥报错,我也解释不清希望大神解惑一下)

      正确思路应该是先写一份到ftp服务器,然后再读取这个文件,然后再把这个文件输出给客户端

    参考:

    ftp服务器搭建(离线安装vsftpd),配置

    poi实现百万级数据导出

    来看代码吧:

    1. 我们只需要对 oi实现百万级数据导出 中的 CommentController  稍作修改,然后配合一些工具类就可以实现

    /**
         * excel导出功能
         * @param commentSearch
         * @param response
         * @param request
         * @return
         * @throws Exception
         */
        @RequestMapping("/exportCommentInfo")
        @ResponseBody
        @NoRepeatRequest
        public BaseDTO exportCommentInfo(CommentSearch commentSearch, HttpServletResponse response, HttpServletRequest request) throws Exception{
            LOGGER.info("CommentController.exportCommentInfo start");
            long startTime = System.currentTimeMillis();
            LOGGER.info("开始下载.........................................");
            List<ErrorInfo> errors = null;
            int result = 0;
            String fileName = FileNameUtils.getExportCommontExcelFileName();
            OutputStream fileOut  = null;
            SXSSFWorkbook workbook = null;
            try {
                LOGGER.debug("classpath: " + fileName);
                workbook = new SXSSFWorkbook(10000);
                commentService.exportCommentInfo(request,workbook, commentSearch);
                // 定义excel文件名
                response.setCharacterEncoding("UTF-8");
                response.setHeader("Content-Disposition", "attachment; filename=""
                        + URLEncoder.encode(fileName, "UTF-8") + """);
                // 定义输出流
                fileOut = response.getOutputStream();
                // 调用导出方法
                //workbook.write(fileOut);
                //写一份到ftp服务器
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                workbook.write(os);
                byte[] b = os.toByteArray();
                ByteArrayInputStream in = new ByteArrayInputStream(b);
    FtpUtil.uploadFileToFtp(fileName,in,fileOut);
           workbook.dispose(); }
    catch (Exception e) { LOGGER.error("InterfaceInfoController.exportInterfaceInfo Exception: ", e); ErrorInfo errorInfo = new ErrorInfo("system.error", "系统异常!"); errors = Arrays.asList(errorInfo); request.getSession().setAttribute("exportStatus","error"); }finally { fileOut.close(); workbook.close(); } LOGGER.info("下载完成....|||||.......用时:" + (System.currentTimeMillis() - startTime)); return tranferBaseDTO(errors, result); }

    1.首先把workbook写到 ByteArrayOutputStream 输出流中,然后转换成 字节数组 byte[] b 在转换成 ByteArrayInputStream 输入流用来写入ftp

           ByteArrayOutputStream os = new ByteArrayOutputStream();
                workbook.write(os);
                byte[] b = os.toByteArray();
                ByteArrayInputStream in = new ByteArrayInputStream(b);
                FtpUtil.uploadFileToFtp(fileName,in,fileOut);

    2.然后转换成 字节数组  在转换成输入流用来写入ftp ,主要看这几个方法

    /**
         * 上传重载 二进制流
         * @param filename
         * @param input
         * @return
         */
        public static boolean uploadFileToFtp(String filename, ByteArrayInputStream input, OutputStream fileOut) {
            getPropertity();
            return uploadFileToFtp( host,  port,  username,  password,  basePath,
                    filePath,  filename,  input, fileOut);
        }
    
      /**
         * Description: 向FTP服务器上传文件 二进制流文件
         * @param host FTP服务器hostname
         * @param port FTP服务器端口
         * @param username FTP登录账号
         * @param password FTP登录密码
         * @param basePath FTP服务器基础目录
         * @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
         * @param filename 上传到FTP服务器上的文件名
         * @return 成功返回true,否则返回false
         */
        public static boolean uploadFileToFtp(String host, String port, String username, String password, String basePath,
                                         String filePath, String filename, ByteArrayInputStream input, OutputStream fileOut) {
            FTPClient ftp = new FTPClient();
            try {
                //开启ftp连接
                boolean result = connectFtp(ftp, host, port, username, password, basePath, filePath);
                if(!result){
                    return result;
                }
                if (FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                    // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
                        if (FTPReply.isPositiveCompletion(ftp.sendCommand("OPTS UTF8", "ON"))) {
                            LOCAL_CHARSET = "UTF-8";
                        }
                }
           //防止中文乱码 filename
    = new String(filename.getBytes(LOCAL_CHARSET),SERVER_CHARSET ); //为了加大上传文件速度,将InputStream转成BufferInputStream , InputStream input BufferedInputStream in = new BufferedInputStream(input); //加大缓存区 ftp.setBufferSize(1024*1024); //设置上传文件的类型为二进制类型 ftp.setFileType(FTP.BINARY_FILE_TYPE); //上传文件 if (!ftp.storeFile(filename, in)) { return false; } //写一份给客户端 FTPFile[] fs = ftp.listFiles(); for (FTPFile ff : fs) { if (ff.getName().equals(filename)) { ftp.retrieveFile(ff.getName(), fileOut); fileOut.close(); } } in.close(); ftp.logout(); } catch (IOException e) { e.printStackTrace(); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException ioe) { } } } return true; } /** * 连接ftp服务器并切换到目的目录 * 调用此方法需手动关闭ftp连接 * @param ftp * @param host * @param port * @param username * @param password * @param basePath * @param filePath * @return */ private static boolean connectFtp( FTPClient ftp,String host, String port, String username, String password, String basePath, String filePath){ boolean result = false; try { int portNum = Integer.parseInt(port); int reply; // 连接FTP服务器 ftp.connect(host, portNum); // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器 ftp.login(username, password); reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return result; } //切换到上传目录 if (!ftp.changeWorkingDirectory(basePath+filePath)) { //如果目录不存在创建目录 String[] dirs = filePath.split("/"); String tempPath = basePath; for (String dir : dirs) { if (null == dir || "".equals(dir)) { continue; } tempPath += "/" + dir; if (!ftp.changeWorkingDirectory(tempPath)) { if (!ftp.makeDirectory(tempPath)) { return result; } else { ftp.changeWorkingDirectory(tempPath); } } } } result = true; } catch (IOException e) { e.printStackTrace(); } return result; } }

    主要是  我们为了加快文件上传速度把刚才传入的 ByteArrayInputStream 转换成了  BufferedInputStream 

    BufferedInputStream in = new BufferedInputStream(input);

    然后我们把  BufferedInputStream 写入到ftp服务器

    ftp.storeFile(filename, in)

    到这里第一步就完成了,接下来是从服务器下载我们刚才上传 文件,然后通过刚才传入的 输出流 fileOut 输出到客户端

     //写一份给客户端
     FTPFile[] fs = ftp.listFiles();
     for (FTPFile ff : fs) {
         if (ff.getName().equals(filename)) {
                 ftp.retrieveFile(ff.getName(), fileOut);
                 fileOut.close();
           }
    }
  • 相关阅读:
    【linux】which和whereis
    【linux】locate介绍
    【linux】find命令详解
    【linux】umask
    【linux】文件目录说明
    【linux】Linux系统信息查看命令大全
    【linux】mkdir -p命令
    【linux】head&&tail
    【linux】less &&more
    【linux】ls常用参数
  • 原文地址:https://www.cnblogs.com/UncleWang001/p/10115427.html
Copyright © 2011-2022 走看看