ftpClient.retrieveFileStream输入流未获取完整导致文件导出一直失败

起因:之前有个需求需要对大批次的图片进行导出,同时还需要导出对应的excel表格,表格中添加对图片的超链接可以直接定位到对应图片。这样的需求有两个使用同样的接口,不同的是一个图片大小为150kb左右,另一个为1Mb左右,某次无聊测试发现1Mb的图片导出接口无论多少张都失败,且没有错误提示。

 之前的代码:

由于使用了ftp连接池,以及多线程压缩,导致笔者一直认为可能是这方面的代码出现了问题,排查多次无果后,想到150kb的图片导出接口没有问题,1Mb的有问题,于是往这方面排查

/**
     * 获取文件的输入流
     * @param fileType
     * @param fileName
     * @return
     */
    public InputStream getDownloadInputStream(String fileType, String fileName) {
        FTPClient ftpClient = ftpPoolService.borrowObject();
        ftpClient.enterLocalPassiveMode();
        InputStream inputStream = null;
        try {
            String path = ftpPoolService.getFtpPoolConfig().getWorkingDirectory()+ DIR_SPLIT + fileType;
            if(!fileType.equals(uploadImageType.BURRONLINEINSPECTION.getDescription())){
                path = path + DIR_SPLIT + fileName.substring(0,8);
            }
            int count = 0;
            while (inputStream == null){
                count ++ ;
                if(count == 10){
                    log.error("获取{}文件输入流失败",fileName);
                    break;
                }
                inputStream = ftpClient.retrieveFileStream(path + DIR_SPLIT + fileName);
                log.info("当前文件{} 输入流是否为空:{}",fileName,inputStream == null?"是":"否");
            }
            if(inputStream == null){
                return new NullInputStream(0);
            }
            return inputStream;
        } catch (Exception e) {
            log.error("获取文件输入流失败",e);
        }finally {
            ftpPoolService.returnObject(ftpClient);
        }
        return new NullInputStream(0);
    }

 最终定位到是由于多线程环境下,ftpClient.retrieveFileStream并不能一次获取到完整的输入流,直接返回归还ftp连接失败,最终一直阻塞,直到超时。所以需要在获取完后关闭输入流,并且通过

ftpClient.completePendingCommand();

来表明输入流已获取完,修改后的代码如下:

    public byte[] getFileInputStream(String fileType, String fileName) throws IOException {
        FTPClient ftpClient = ftpPoolService.borrowObject();
        ftpClient.enterLocalPassiveMode();
        InputStream inputStream = null;
        byte[] bytes = null;
        try {
            String path = ftpPoolService.getFtpPoolConfig().getWorkingDirectory()+ DIR_SPLIT + fileType + DIR_SPLIT + fileName.substring(0,8);
            int count = 0;
            while (inputStream == null){
                count ++ ;
                if(count == 10){
                    log.error("获取{}文件输入流失败",fileName);
                    break;
                }
                inputStream = ftpClient.retrieveFileStream(path + DIR_SPLIT + fileName);
                log.info("当前文件{} 输入流是否为空:{}",fileName,inputStream == null?"是":"否");
            }
            if(inputStream == null){
                return new byte[0];
            } else{
                bytes = IOUtils.toByteArray(inputStream);
                if (inputStream != null) {
                    inputStream.close();
                }
            }
            return bytes;
        } catch (Exception e) {
            log.error("获取文件输入流失败",e);
        }finally {
            ftpClient.completePendingCommand();
            ftpPoolService.returnObject(ftpClient);
        }
        return new byte[0];
    }

外部使用

InputStream inputStream = new ByteArrayInputStream(fileInputStream);

将字节数组转换为输入流即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顾十方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值