解决InputStream流无法重复使用的问题

一.需求

现在有个需求,要通过InputStream流先去判断文件类型,然后再上传文件,这样就会用到两次InputStream。

二.问题

这个功能之前的同事已经做了一版,一直以为是正常的,毕竟都很久了,但是我用的时候发现上传的文件总是空的,只能去仔细看下代码了。

三.排查

try (InputStream in = inputStream) {
            //检验文件
            CheckFileUtil.checkFile(inputStream, FileUtil.extName(filename));
            LoggerFactory.getLogger(this.getClass()).info("上传文件的文件名="+filename);
            //上传文件
            String filePathURL = saveToDisk(in, FileUtil.extName(filename));

            FileInfo fileInfo = new FileInfo();
            fileInfo.setId(RandomUtil.simpleUUID());
            fileInfo.setFileName(filename);
            fileInfo.setFileType(FileUtil.extName(filename));

之前的代码逻辑是用原来的inputStream去校验,然后用赋值后的in去上传文件,开始看到这里也没发现有什么问题,感觉很正常。

只能去加日志,打断点调试了,最终发现在校验文件之后,不管是inputStream还是in都是空的了,恍然大悟。由于流读过一次就不能再读了。

四.解决

开始想着去复制一遍这个流就行了,查了下才知道不行,InputStream对象本身不能复制,它也没有实现Cloneable接口。

那就先用byte[]去存储,然后用的时候在转换。调整后的代码

public static byte[] readInputStreamToByteArray(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, bytesRead);
        }
        return byteArrayOutputStream.toByteArray();
    }

    @Override
    public FileInfo upload(String filename, Long size, InputStream inputStream) {
        try (InputStream in = inputStream) {
            byte[] bytes = readInputStreamToByteArray(in);
            //检验文件
            CheckFileUtil.checkFile(new ByteArrayInputStream(bytes), FileUtil.extName(filename));
            LoggerFactory.getLogger(this.getClass()).info("上传文件的文件名="+filename);
            //上传文件
            String filePathUrl = saveToDisk(new ByteArrayInputStream(bytes), FileUtil.extName(filename));

解决InputStream流无法重复使用的问题_第1张图片

但是这种明显只适用于文件不大的时候,不知道如果文件较大的情况下,该怎么进一步优化,先记录下,后面遇到了再补充

你可能感兴趣的:(java,java,开发语言)