工作实战之大文件上传minio

这篇具有很好参考价值的文章主要介绍了工作实战之大文件上传minio。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、完成的现象

二、核心代码

1.前端核心代码

2.后端核心代码

三、代码下载地址

总结


前言

文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法

大文件上传,要解决的问题:

1.文件太大,请求限制,2.文件太大,耗时太久,连接超时

解决方案:采用分片的方式进行上传

前端用百度开源的WebUploader进行分片异步上传

后端用minio的putObject上传,composeObject合并,完成大文件的上传


一、完成的现象

工作实战之大文件上传minio

工作实战之大文件上传minio

 工作实战之大文件上传minio

 工作实战之大文件上传minio

二、核心代码

1.前端核心代码

WebUploader 是由 Baidu WebFE (FEX) 团队开发的一个简单的以 HTML5 为主,FLASH 为辅的现代文件上传组件

// HOOK 这个必须要再uploader实例化前面
    WebUploader.Uploader.register({
        'before-send-file': 'beforeSendFile',
        'before-send': 'beforeSend'
    }, {
        beforeSendFile: function (file) {
            console.log("beforeSendFile");
            // Deferred对象在钩子回掉函数中经常要用到,用来处理需要等待的异步操作。
            var task = new $.Deferred();
            // 根据文件内容来查询MD5
            uploader.md5File(file).progress(function (percentage) {   // 及时显示进度
                console.log('计算md5进度:', percentage);
                getProgressBar(file, percentage, "MD5", "MD5进度");
            }).then(function (val) { // 完成
                console.log('md5 result:', val);
                file.md5 = val;
                // 模拟用户id
                // file.uid = new Date().getTime() + "_" + Math.random() * 100;
                file.uid = WebUploader.Base.guid();
                // 进行md5判断
                $.post("index/checkFileMd5", {uid: file.uid, md5: file.md5},
                        function (data) {
                            console.log(data.status);
                            var status = data.status.value;
                            task.resolve();
                            if (status == 101) {
                                // 文件不存在,那就正常流程
                            } else if (status == 100) {
                                // 忽略上传过程,直接标识上传成功;
                                uploader.skipFile(file);
                                file.pass = true;
                            } else if (status == 102) {
                                // 部分已经上传到服务器了,但是差几个模块。
                                file.missChunks = data.data;
                            }
                        });
            });
            return $.when(task);
        },
        beforeSend: function (block) {
            console.log("block")
            var task = new $.Deferred();
            var file = block.file;
            var missChunks = file.missChunks;
            var blockChunk = block.chunk;
            console.log("当前分块:" + blockChunk);
            console.log("missChunks:" + missChunks);
            if (missChunks !== null && missChunks !== undefined && missChunks !== '') {
                var flag = true;
                for (var i = 0; i < missChunks.length; i++) {
                    if (blockChunk == missChunks[i]) {
                        console.log(file.name + ":" + blockChunk + ":还没上传,现在上传去吧。");
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    task.reject();
                } else {
                    task.resolve();
                }
            } else {
                task.resolve();
            }
            return $.when(task);
        }
    });

    // 实例化
    var uploader = WebUploader.create({
        pick: {
            id: '#picker',
            label: '点击选择文件'
        },
        formData: {
            uid: 0,
            md5: '',
            chunkSize: chunkSize
        },
        //dnd: '#dndArea',
        //paste: '#uploader',
        swf: 'js/Uploader.swf',
        chunked: true,
        chunkSize: chunkSize, // 字节 5M分块
        threads: 5,
        server: 'index/fileUpload',
        auto: true,

        // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
        disableGlobalDnd: true,
        fileNumLimit: 1024,
        fileSizeLimit: 1024 * 1024 * 1024,    // 200 M
        fileSingleSizeLimit: 1024 * 1024 * 1024    // 50 M
    });

    // 当有文件被添加进队列的时候
    uploader.on('fileQueued', function (file) {
        console.log("fileQueued");
        $thelist.append('<div id="' + file.id + '" class="item">' +
                '<h4 class="info">' + file.name + '</h4>' +
                '<p class="state">等待上传...</p>' +
                '</div>');
    });


    // 上传中
    uploader.on('uploadProgress', function (file, percentage) {
        getProgressBar(file, percentage, "FILE", "上传进度");
    });
    // 上传返回结果
    uploader.on('uploadSuccess', function (file) {
        var text = '已上传';
        if (file.pass) {
            text = "文件妙传功能,文件已上传。"
        }
        $('#' + file.id).find('p.state').text(text);
    });
    uploader.on('uploadError', function (file) {
        $('#' + file.id).find('p.state').text('上传出错');
    });
    uploader.on('uploadComplete', function (file) {
        // 隐藏进度条
         fadeOutProgress(file, 'MD5');
        // fadeOutProgress(file, 'FILE');
    });
    // 文件上传
    $btn.on('click', function () {
        console.log("上传...");
        uploader.upload();
        console.log("上传成功");
    });

    /**
     *  生成进度条封装方法
     * @param file 文件
     * @param percentage 进度值
     * @param id_Prefix id前缀
     * @param titleName 标题名
     */
    function getProgressBar(file, percentage, id_Prefix, titleName) {
        var $li = $('#' + file.id), $percent = $li.find('#' + id_Prefix + '-progress-bar');
        // 避免重复创建
        if (!$percent.length) {
            $percent = $('<div id="' + id_Prefix + '-progress" class="progress progress-striped active">' +
                    '<div id="' + id_Prefix + '-progress-bar" class="progress-bar" role="progressbar" style="width: 0%">' +
                    '</div>' +
                    '</div>'
            ).appendTo($li).find('#' + id_Prefix + '-progress-bar');
        }
        var progressPercentage = Math.ceil(percentage * 100) + '%';
        $percent.css('width', progressPercentage);
        $percent.html(titleName + ':' + progressPercentage);
    }

   

2.后端核心代码

MinIO提供高性能、S3兼容的对象存储。Minio 是一个基于Go语言的对象存储服务。它实现了大部分亚马逊S3云存储服务接口,可以看做是是S3的开源版本,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等

@Override
    public void uploadFileToMinio(MultipartFileParam param) throws Exception {
        String md5 = param.getMd5();
        //总分片数
        int totalPieces = param.getChunks();
        //当前分片
        int sliceIndex = param.getChunk();
        // 可以最后一个分片传文件名用来保存
        String fileName = param.getName();
        //上传文件
        MultipartFile file = param.getFile();
        // 上传
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(minIoClientConfig.getTmpBucketName())
                        .object(md5.concat("/").concat(Integer.toString(sliceIndex)))
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build());
        //判断是否全部上传完成
        if(isUploadComplete(md5,totalPieces)) {
            log.info("上传临时目录完成--------------");
            //合并文件
            mergeFile(totalPieces,md5,fileName);
            // 删除所有的分片文件
            deleteTempFile(totalPieces,md5);
            log.info("完成上传");
        }
    }

 /**
     * 删除临时文件
     * @param totalPieces
     * @param md5
     */
    private void deleteTempFile(int totalPieces,String md5) {
        List<DeleteObject> delObjects = Stream.iterate(0, i -> ++i)
                .limit(totalPieces)
                .map(i -> new DeleteObject(md5.concat("/").concat(Integer.toString(i))))
                .collect(Collectors.toList());
        log.info("删除临时分片:{}",delObjects);
        minioClient.removeObjects(
                RemoveObjectsArgs.builder().bucket(minIoClientConfig.getTmpBucketName())
                        .objects(delObjects).build());
    }

    /**
     * 合并文件
     * @param totalPieces
     * @param md5
     * @param fileName
     * @throws Exception
     */
    private void mergeFile(int totalPieces,String md5,String fileName) throws Exception{
        // 完成上传从缓存目录合并迁移到正式目录
        List<ComposeSource> sourceObjectList = Stream.iterate(0, i -> ++i)
                .limit(totalPieces)
                .map(i -> ComposeSource.builder()
                        .bucket(minIoClientConfig.getTmpBucketName())
                        .object(md5.concat("/").concat(Integer.toString(i)))
                        .build())
                .collect(Collectors.toList());

        minioClient.composeObject(
                ComposeObjectArgs.builder()
                        .bucket(minIoClientConfig.getBucketName())
                        .object(fileName)
                        .sources(sourceObjectList)
                        .build());
    }

/**
     * 是否上传完成
     * @param md5
     * @param totalPieces
     * @return
     * @throws Exception
     */
    private boolean isUploadComplete(String md5,int totalPieces) throws Exception{
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(minIoClientConfig.getTmpBucketName())
                        .prefix(md5.concat("/")).build());
        Set<String> objectNames = Sets.newHashSet();
        for (Result<Item> item : results) {
            objectNames.add(item.get().objectName());
        }
        return objectNames.size()==totalPieces;
    }

三、代码下载地址

代码:https://gitee.com/zenglx/big-file-upload.git

总结

当我们在做文件上传的功能时,如果上传的文件过大,可能会导致长传时间特别长,且上传失败后需要整个文件全部重新上传。因此,我们需要前后端配合来解决这个问题。

最常用的解决方案就是 —— 切片上传。

文件切片上传
文件秒传
文件断点续传
 文章来源地址https://www.toymoban.com/news/detail-453739.html

到了这里,关于工作实战之大文件上传minio的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Minio上传文件和安装快速使用

    目录 1.前置条件 2.Minio的安装 3.Minio使用 3.1导入依赖可查看 3.2查看图形化界面 3.3 查看桶设置 ps:MultipartFile传输文件的时候,默认最大字节显示1048576个字节 1MB大小  需要添加额外参数 前置:安装docker 官网:Java Quickstart Guide — MinIO Object Storage for Linux 使用原因 : 1.存储大容量

    2023年04月09日
    浏览(33)
  • springboot实现文件上传到minio

    一、前言 最近在项目中用的使用minio来上传文件,因此在这里给告诉大家如何实现 二、实现文件上传至minio 1.添加相关的maven依赖 2.minio连接配置 (1)首先配置minio属性 (2)接着配置minio连接,代码如下: (3)在YAML添加minio配置 3.定义minio工具类,代码如下: 4.编写实现文件

    2024年02月09日
    浏览(39)
  • springboot实现minio文件分片上传

    在Spring Boot中实现MinIO的文件分片上传涉及到几个关键步骤。MinIO是一个高性能的分布式对象存储服务,它兼容Amazon S3的API。分片上传主要用于上传大文件,将大文件分成多个部分,分别上传,最后再将这些部分合并成一个完整的文件。这样做的好处是提高了上传的可靠性,并

    2024年01月17日
    浏览(60)
  • SpringBoot上传文件到Minio服务器,支持批量上传

    本文主要介绍如何使用SpringBoot上传到minio服务器。 没什么可多说的,公司用什么咱们开发研究什么就完事了。直接分享核心代码。 minio依赖 配置文件 首先是核心的参数,包括服务器minio地址,以及用户名密码,使用的桶名称 controller代码 如果只需要上传文件,只需要Multipa

    2024年02月08日
    浏览(47)
  • SpringBoot整合Minio实现文件上传、下载

    SpringBoot整合Minio实现文件上传、下载: 1,介绍高性能分布式存储文件服务Minio:Minio是 基于Go语言编写的对象存储服务 , 适合于存储大容量非结构化的数据 ,例如 图片、音频、视频、日志文件、备份数据和容器/虚拟机镜像等 ,而一个对象文件可以是任意大小,从几kb到最

    2024年02月06日
    浏览(47)
  • OSS文件上传、MinIO分布式文件存储系统

    阿里云OSS上传图片 实现步骤: 1. 定义OSS相关配置 application-dev.yml application.yml 2. 读取OSS配置 在sky-common模块中,已定义 3. 生成OSS工具类对象 在sky-server模块 其中,AliOssUtil.java已在sky-common模块中定义 4. 定义文件上传接口 在sky-server模块中定义接口 MinIO分布式文件存储系统 MinI

    2024年01月24日
    浏览(45)
  • 上传视频文件,基于断点续传(整合Minio)

    目录 1、什么是断点续传 2、分块文件 3、合并文件 4、 Minio 分布式文件系统整合断点续传 4.1 进行文件分块上传到 Minio  4.2 进行 Minio 中分块文件的合并 5、使用 Minio 进行断点续传的注意事项           相信很多小伙伴在上传下载图片或者视频的时候,突然间(没错就是这

    2024年02月11日
    浏览(46)
  • SpringBoot+MinIO 实现文件上传、读取、下载、删除

    一、 MinIO 二、 MinIO安装和启动 三、 pom.xml 四、 applicatin.properties(配置文件) 五、 编写Java业务类

    2024年02月09日
    浏览(44)
  • 【minio】Ubuntu安装MinIO文件服务器并通过C++上传下载

    😏 ★,° :.☆( ̄▽ ̄)/$: .°★ 😏 这篇文章主要介绍MinIO的使用。 学其所用,用其所学。——梁启超 欢迎来到我的博客,一起学习知识,共同进步。 喜欢的朋友可以关注一下,下次更新不迷路🥞 MinIO是一种高性能、可扩展的 对象存储服务 ,它可以在私有云、公共云和边缘计

    2024年02月08日
    浏览(55)
  • 【分布式文件存储】MinIO部署及实现文件上传下载

    目录 概述 MinIO集群部署 准备docker-compose.yml 测试启动 MinIO用户管理 Buckets管理  创建Buckets MinIO客户端 引入依赖   文件上传下载Demo 调用API碰到的问题 MinIO | 高性能, Kubernetes 原生对象存储 MinIO是全球领先的对象存储先锋,目前在全世界有数百万的用户。 高性能 ,在标准硬件

    2024年02月07日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包