java中使用NIO非阻塞读取图片文件

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

//获取图片资源
@RequestMapping("/getResource")
public void getResource(HttpServletResponse response, @NotEmpty String sourceName) {
    if (!StringTools.pathIsOk(sourceName)) {
        throw new BusinessException(ResponseCodeEnum.CODE_600);
    }
    String suffix = StringTools.getFileSuffix(sourceName);
    FileTypeEnum fileTypeEnum = FileTypeEnum.getBySuffix(suffix);
    if (fileTypeEnum == null) {
        throw new BusinessException(ResponseCodeEnum.CODE_600);
    }
    switch (fileTypeEnum) {
        case IMAGE: //".jpeg", ".jpg", ".png", ".gif", ".bmp", ".webp"
            //缓存30天
            response.setHeader("Cache-Control", "max-age=" + 30 * 24 * 60 * 60);
            response.setContentType("image/" + suffix.replace(".", ""));
            break;
    }
    readFile(response, sourceName);
}

//使用NIO非阻塞来读取字节流的文件
protected void readFile(HttpServletResponse response, String filePath) {
    Path path = Paths.get(appConfig.getProjectFolder() + Constants.FILE_FOLDER + filePath);
    File file = path.toFile();
    if (!file.exists()) {
        return;
    }
    // 使用 Channels.newChannel 将传统IO流 OutputStream 转换为 NIO的通道 WritableByteChannel
    try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ); //以只读模式打开文件通道。
         WritableByteChannel outChannel = Channels.newChannel(response.getOutputStream())) {
            ByteBuffer buffer = ByteBuffer.allocate(8192); // allocate 分配8192字节(8kb)的缓冲区
            while (fileChannel.read(buffer) != -1) {//从文件通道读取数据到缓冲区,如果返回值为-1表示已经读取到文件末尾。 (写模式)
                buffer.flip(); // 将 写模式(将数据写入缓冲区) 切换到 读模式(从缓冲区中读取数据) ; 将 position 重置为0(表示从缓冲区的开头开始读取)
                outChannel.write(buffer);//将缓冲区中的数据写入响应输出通道。
                buffer.clear(); // 清空缓冲区,准备下一次读取
            }
            response.getOutputStream().flush();//刷新输出流,将缓冲区中的数据发送给客户端。
    } catch (IOException e) {
        log.error("读取文件异常", e);
    }
}

对比普通的字节流读取方式

protected void readFile1(HttpServletResponse response, String filePath) {
    File file = new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER + filePath);
    if (!file.exists()) {
        return;
    }
    try (OutputStream out = response.getOutputStream(); FileInputStream in = new FileInputStream(file)) {
        byte[] byteData = new byte[1024];
        int len = 0;
        while ((len = in.read(byteData)) != -1) {
            out.write(byteData, 0, len);
        }
        out.flush();
    } catch (Exception e) {
        log.error("读取文件异常", e);
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值