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();
       }}

原文地址:https://www.cnblogs.com/UncleWang001/p/10115427.html

时间: 2024-10-23 22:18:13

POI导出时写一份到ftp服务器,一份下载给客户端的相关文章

Java通过FTP服务器上传下载文件的解决方案

对于使用文件进行交换数据的应用来说,使用FTP 服务器是一个很不错的解决方案.本文使用Apache Jakarta Commons Net(commons-net-3.3.jar)基于FileZilla Server服务器实现FTP服务器上文件的上传/下载/删除等操作. 关于FileZilla Server服务器的详细搭建配置过程,详情请见FileZilla Server安装配置教程.之前有朋友说,上传大文件(几百M以上的文件)到FTP服务器时会重现无法重命名的问题,但本人亲测上传2G的文件到F

使用批处理文件在FTP服务器 上传下载文件

1.从ftp服务器根目录文件夹下的文件到指定的文件夹下 格式:ftp -s:[配置文件] [ftp地址] 如:ftp -s:c:\vc\ftpconfig.txt   192.168.1.1 建立一个批处理文件:命名为 test.bat(名称可以随便,为了方便操作,直接命名为1.bat)  然后将上面的内容拷贝进去 ftpconfig.txt的文件内容是: testuser test get test.exe    C:\ftptest\testdownload.exe bye 解释: 前两条命

Spring中利用组件实现从FTP服务器上传/下载文件

FtpUtil.java import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.ne

WordPress更新时提示无法连接到FTP服务器的解决方案

这几天在搭建主站的时候,更新wordpress时无法连接到FTP原因服务器 解决方法如下: 在WordPress目录下找到wp-config.php文件并编辑,在最后一行加上: define('FS_METHOD', "direct"); 原文地址:https://www.cnblogs.com/ECJTUACM-873284962/p/9191377.html

从ftp服务器进行批量下载,处理文件名保存时重名的问题,更改重名文件名方式为给后面加1、2、3等数字,保持后缀不变

公司最近有一个从ftp批量下载文件的需求,但是文件名重复总会报错 没办法,自己下班后写了一个小算法 仿照桶排序的原理,实现了这个小功能,直接上代码: String[] test = {"hahaha.txt","wekje.doc","学习.pdf","wekje.doc","学习.pdf", "hahaha.txt","学习.pdf","wekje.doc

Ubantu下FTP服务器资源进行控制

在FTP服务器的管理中无论对本地用户还是匿名用户,对于FTP服务器资源的使用都需要进行控控制, 避免由于负担过大造成FTP服务器运行异常, 可以添加以下配置项对FTP客户机使用FTP服务器资源进行控制: max_client 设置项用于设置FTP服务器所允许的最大客户端连接数,值为0时表示不限制.例如max_client=100表示FTP服务器的所有客户端最大连接数不超过100个. max_per_ip 设置项用于设置对于同一IP地址允许的最大客户端连接数,值为0时表示不限制.例如max_per

CentOS8搭建FTP服务器

1 概述 文章主要讲了CentOS8如何利用vsftpd搭建一个FTP服务器,然后进行简单的匿名上传/下载与用户上传/下载测试,还有使用了wget测试. 2 安装vsftpd yum install -y vsftpd 3 开启服务 service httpd start 4 设置开机启动 可以用 systemctl list-unit-files | grep vsftpd 查看是否开机启动.显示disabled.通过 chkconfig vsftpd on 开启自启,再次执行systemct

在Windows 2003下搭建FTP服务器

Windows 2003 Standard Edition.Windows 2003 Enterprise Edition.Windows XP Professional .Windows 2000 Server.Windows 2000 Advanced Server 以及 Windows 2000 Professional 的默认安装都带有 IIS .在系统的安装过程中IIS是默认不安装的,在系统安装完毕后可以通过添加删除程序加装 IIS. IIS 是微软推出的架设 WEB.FTP.SMTP

Windows Server 2003 IIS 中设置 FTP 服务器

Windows 7 .Windows 2003 Standard Edition.Windows 2003 Enterprise Edition.Windows XP .Windows 2000 Server.Windows 2000 Advanced Server 以及 Windows 2000 Professional 的默认安装都带有 IIS . 在系统的安装过程中IIS是默认不安装的,在系统安装完毕后可以通过添加删除程序加装 IIS. IIS 是微软推出的架设 WEB.FTP.SMTP