java WebUploader 分片上传

对于大文件的处理,无论是用户端还是服务端,如果一次性进行读取发送、接收都是不可取,很容易导致内存问题。所以对于大文件上传,采用切块分段上传,从上传的效率来看,利用多线程并发上传能够达到最大效率。

 本文是基于 springboot + vue 实现的文件上传,本文主要介绍服务端实现文件上传的步骤及代码实现,vue的实现步骤及实现请移步本人的另一篇文章

详细思路及源码

上传分步:

本人分析上传总共分为:

  • 检查文件是否已上传,如已上传可实现秒传

  • 创建临时文件(._tmp)和上传的配置文件(.conf)

  • 使用RandomAccessFile获取临时文件

  • 调用RandomAccessFile的getChannel()方法,打开文件通道 FileChannel

  • 获取当前是第几个分块,计算文件的最后偏移量

  • 获取当前文件分块的字节数组,用于获取文件字节长度

  • 使用文件通道FileChannel类的 map()方法创建直接字节缓冲器 MappedByteBuffer

  • 将分块的字节数组放入到当前位置的缓冲区内 mappedByteBuffer.put(byte[] b)

  • 释放缓冲区

  • 检查文件是否全部完成上传,如上传完成将临时文件名为正式文件名

直接上代码

public class FlieChunkUtils {
 
    /**
     * 分块上传
     * 第一步:获取RandomAccessFile,随机访问文件类的对象
     * 第二步:调用RandomAccessFile的getChannel()方法,打开文件通道 FileChannel
     * 第三步:获取当前是第几个分块,计算文件的最后偏移量
     * 第四步:获取当前文件分块的字节数组,用于获取文件字节长度
     * 第五步:使用文件通道FileChannel类的 map()方法创建直接字节缓冲器  MappedByteBuffer
     * 第六步:将分块的字节数组放入到当前位置的缓冲区内  mappedByteBuffer.put(byte[] b);
     * 第七步:释放缓冲区
     * 第八步:检查文件是否全部完成上传
     *
     * @param param
     * @return
     * @throws Exception
     */
    public static ApiResult uploadByMappedByteBuffer(MultipartFileParam param) throws Exception {
        if (param.getIdentifier() == null || "".equals(param.getIdentifier())) {
            param.setIdentifier(UUID.randomUUID().toString());
        }
        // 判断是否上传
        if (ObjectUtil.isEmpty(param.getFile())) {
            return checkUploadStatus(param);
        }
        // 文件名称
        String fileName = getFileName(param);
        // 临时文件名称
        String tempFileName = param.getIdentifier() + fileName.substring(fileName.lastIndexOf(".")) + "_tmp";
        // 获取文件路径
        String filePath = getUploadPath(param);
        // 创建文件夹
        FileUploadUtils.getAbsoluteFile(filePath, fileName);
        // 创建临时文件
        File tempFile = new File(filePath, tempFileName);
        //第一步 获取RandomAccessFile,随机访问文件类的对象
        RandomAccessFile raf = RandomAccessFileUitls.getModelRW(tempFile);
        //第二步 调用RandomAccessFile的getChannel()方法,打开文件通道 FileChannel
        FileChannel fileChannel = raf.getChannel();
        //第三步 获取当前是第几个分块,计算文件的最后偏移量
        long offset = (param.getChunkNumber() - 1) * param.getChunkSize();
        //第四步 获取当前文件分块的字节数组,用于获取文件字节长度
        byte[] fileData = param.getFile().getBytes();
        //第五步 使用文件通道FileChannel类的 map()方法创建直接字节缓冲器  MappedByteBuffer
        MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, offset, fileData.length);
        //第六步 将分块的字节数组放入到当前位置的缓冲区内  mappedByteBuffer.put(byte[] b)
        mappedByteBuffer.put(fileData);
        //第七步 释放缓冲区
        freeMappedByteBuffer(mappedByteBuffer);
        fileChannel.close();
        raf.close();
        //第八步 检查文件是否全部完成上传
        ApiResult

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr_Zang666

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

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

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

打赏作者

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

抵扣说明:

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

余额充值