来看看windows和linux下getResourceAsStream方法的坑及完美解决方案

需求:下载导入模板返回流的形式给前端

文件位置:项目resources文件下(这里没说写死文件路径的,个人想法不提倡)在这里插入图片描述

坑:

  1. 使用TestFileUtil.class.getClassLoader().getResourceAsStream,inputStream.available()在windows下 获取流长度正常,但是在linux下获取长度为0,导致new byte[]长度为0,读不进去
  2. 在1的基础上in.available()方法修改为while循环读流的方式,但是这种方式读出来的流与正确的有差异
  3. 在2的基础上while循环读流的方式,用两个for循环解决,能解决,但是有点复杂

解决方案:使用getResourceAsStream,使用IoUtil.readBytes(输入流,是否关闭流)完美解决

接下来进行代码解说,先上解决方案,后面一步一步解说坑

前置准备

package com.***.vo.rsp;

import lombok.Data;

import java.io.Serializable;

/**
 * @author longwei
 * @Description 文件转base64DTO
 * @date 2020/7/7 17:33
 */
@Data
public class FileBase64DTO implements Serializable {

    private static final Long serialVersionUID = 1L;

    // 文件转base64字符串
    private String fileBaseStr;

    // 文件名
    private String fileName;

    public FileBase64DTO(String fileBaseStr, String fileName) {
        this.fileBaseStr = fileBaseStr;
        this.fileName = fileName;
    }

    public static FileBase64DTO getFileBase64DTO(String fileBaseStr, String fileName) {
        return new FileBase64DTO(fileBaseStr,fileName);
    }

}

请求:
在这里插入图片描述

解决方案:使用getResourceAsStream,使用IoUtil.readBytes(输入流,是否关闭流)完美解决

package com.***.utils;

import cn.hutool.core.io.IoUtil;
import com.***.vo.rsp.FileBase64DTO;
import org.apache.commons.codec.binary.Base64;

import java.io.IOException;
import java.io.InputStream;

/**
 * 文件上传工具类
 */
public class TestFileUtil {

    /**
     * 文件转为base64字符串
     * 解决方案:使用ResourceAsStream,使用IoUtil.readBytes(输入流,是否关闭流)完美解决
     * @param filePath 文件路径
     * @param fileName 文件名
     * @author longwei
     */
    public static FileBase64DTO fileToBase64Str(String filePath, String fileName) {
        InputStream in = null;
        String base64;
        try {
            in = TestFileUtil.class.getClassLoader().getResourceAsStream(filePath);
            byte[] bytes = IoUtil.readBytes(in, true);
            base64 = new String(Base64.encodeBase64(bytes), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("下载文件失败,请相关人员检查");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return FileBase64DTO.getFileBase64DTO(base64, fileName);
    }

}

本地windows输出:
在这里插入图片描述

linux服务器输出:
在这里插入图片描述

以上为解决方案,接下来一步一步解说坑

1、使用TestFileUtil.class.getClassLoader().getResourceAsStream,inputStream.available()在windows下 获取流长度正常,但是在linux下获取长度为0,导致new byte[]长度为0,读不进去

/**
 * 文件转为base64字符串
 * 坑:在windows下 inputStream.available()获取流长度正常,但是在linux下获取长度为0,导致new byte[]长度为0,读不进去
 * @param filePath 文件路径
 * @param fileName 文件名
 * @author longwei
 */
public static FileBase64DTO fileToBase64Str(String filePath, String fileName) {
    InputStream in = null;
    String base64;
    try {
        System.out.println("filePath:"+filePath);
        System.out.println("==================");
        in = TestFileUtil.class.getClassLoader().getResourceAsStream(filePath);
        System.out.println("available:"+in.available());
        System.out.println("==================");
        byte[] bytes = new byte[in.available()];
        in.read(bytes);
        base64 = new String(Base64.encodeBase64(bytes), "UTF-8");
        System.out.println("base64:"+base64);
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("下载文件失败,请相关人员检查");
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return FileBase64DTO.getFileBase64DTO(base64, fileName);
}

本地windows输出:
在这里插入图片描述

linux服务器输出:in.available() 为0
在这里插入图片描述

2、在1的基础上in.available()方法修改为while循环读流的方式,但是这种方式读出来的流与正确的有差异

/**
 * 文件转为base64字符串
 * 在1的基础上in.available()方法修改为while循环读流的方式,但是这种方式读出来的流与正确的有差异
 * @param filePath 文件路径
 * @param fileName 文件名
 * @author longwei
 */
public static FileBase64DTO fileToBase64Str2(String filePath, String fileName) {
    StringBuilder stringBuilder=new StringBuilder();
    InputStream in = null;
    try {
        ClassPathResource resource=new ClassPathResource(filePath);
        in = resource.getInputStream();
        byte[] bytes = new byte[1024];
        int len = -1;
        while ((len = in.read(bytes)) != -1) {
            stringBuilder.append(new String(Base64.encodeBase64(bytes), "UTF-8"));
        }
        System.out.println(stringBuilder.toString());
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("下载文件失败,请相关人员检查");
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return FileBase64DTO.getFileBase64DTO(stringBuilder.toString(), fileName);
}

本地windows控制台输出:流差异
在这里插入图片描述

3、在2的基础上while循环读流的方式,用两个for循环解决,能解决,但是有点复杂

/**
 * 文件转为base64字符串
 * 在2的基础上while循环读流的方式,用两个for循环解决,能解决,但是有点复杂
 * @param filePath 文件路径
 * @param fileName 文件名
 * @author longwei
 */
public static FileBase64DTO fileToBase64Str2(String filePath, String fileName) {
    InputStream in = null;
    String base64;
    List<Byte> list=new LinkedList<>();
    try {
        in = TestFileUtil.class.getClassLoader().getResourceAsStream(filePath);
        byte[] bys = new byte[1024];
        int len; //len代表读取到的数据的长度
        while ((len = in.read(bys)) != -1) {
            for (int i = 0; i <len ; i++) {
                list.add(bys[i]);
            }
        }

        byte[] bytes=new byte[list.size()];
        for (int i = 0; i <list.size() ; i++) {
            bytes[i]=list.get(i);
        }
        base64 = new String(Base64.encodeBase64(bytes), "UTF-8");
        System.out.println(base64);
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("下载文件失败,请相关人员检查");
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return FileBase64DTO.getFileBase64DTO(base64, fileName);
}

本地windows控制台输出:正确
在这里插入图片描述

结论:使用getResourceAsStream,使用IoUtil.readBytes(输入流,是否关闭流)完美解决读文件流的问题

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值