springboot整合minio+vue实现大文件分片上传,断点续传(复制可用,包含minio工具类)

您所在的位置:网站首页 上海二手房涨幅最大的房价总价区间 springboot整合minio+vue实现大文件分片上传,断点续传(复制可用,包含minio工具类)

springboot整合minio+vue实现大文件分片上传,断点续传(复制可用,包含minio工具类)

2024-03-26 04:27| 来源: 网络整理| 查看: 265

前言

大文件分片上传和断点续传是为了解决在网络传输过程中可能遇到的问题,以提高文件传输的效率和稳定性。

首先,大文件分片上传是将大文件分割成较小的片段进行上传。这样做的好处是可以减少单个文件的传输时间,因为较小的文件片段更容易快速上传到目标服务器。同时,如果在传输过程中出现错误或中断,只需要重新上传出现问题的文件片段,而不需要重新上传整个文件,从而减少了传输的时间和带宽消耗。

其次,断点续传是指在文件传输过程中,如果传输被中断或者发生错误,可以从上一次中断的地方继续传输,而不是从头开始。这对于大文件的传输尤为重要,因为传输一个大文件可能需要较长的时间,而中断可能是由网络问题、电源故障、软件崩溃或其他因素引起的。断点续传功能允许用户在中断后恢复传输,而无需重新开始,节省了时间和资源。

大文件分片上传和断点续传在以下情况下尤为重要:

低带宽网络环境:在网络速度较慢或不稳定的情况下,将大文件分割为较小的片段进行上传可以降低传输的时间和失败的风险。大文件传输:对于大文件,一次性完整上传可能需要很长时间,而且中途出现问题时需要重新传输整个文件,因此将文件分割并实现断点续传功能可以提高效率和可靠性。网络中断或传输错误:网络中断、电源故障或软件崩溃等因素可能导致文件传输中断,断点续传功能可以从中断处恢复,避免重新传输整个文件。多用户并发上传:在有多个用户同时上传文件的情况下,分片上传和断点续传可以减少对服务器资源的占用,提高并发传输的效率。 前期准备

image-20230520204308171

如果项目是通过nginx转发的,那么在nginx中需要有如下配置

# 以下为默认值,第一行是默认超时时间75s,第二行默认请求体式1m,需要调大。这两个参数在nginx.conf下的http下 keepalive_timeout 75; client_max_body_size 1m;

springboot配置文件中的配置

# 其中,spring.servlet.multipart.max-file-size定义了单个文件的最大大小,而spring.servlet.multipart.max-request-size定义了整个请求的最大大小(包括所有文件和其他请求参数)。需要根据需求自己调大 spring.servlet.multipart.max-file-size=1MB spring.servlet.multipart.max-request-size=10MB 后端实现

⏮:首先需要服务器中搭建有minio,这个搭建起来很快的,当然如果不是minio,别的oss也可以

minio搭建

1️⃣:需要的依赖

io.minio minio 8.2.0

2️⃣:minio在properties中的相关配置

# 服务地址 minio.endpoint=http://127.0.0.1:9000 # 账号 minio.accessKey=admin # 密码 minio.secretKey=123456 # 桶名称 minio.bucketName=xiaobo

3️⃣:配置和创建MinIO客户端以及其工具类

package com.todoitbo.tallybookdasmart.config; import com.todoitbo.tallybookdasmart.exception.BusinessException; import io.minio.MinioClient; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author xiaobo * @date 2022/8/5 */ @Data @Configuration @Slf4j public class MinIoClientConfig { @Value("${minio.endpoint}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; /** * 注入minio 客户端 * * @return MinioClient */ @Bean public MinioClient minioClient() { try { return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build(); } catch (Exception e) { throw new BusinessException("-----创建Minio客户端失败-----", e.getMessage()).setCause(e).setLog(); } } }

4️⃣:minio的工具类

package com.todoitbo.tallybookdasmart.utils; import com.alibaba.fastjson2.JSON; import com.todoitbo.tallybookdasmart.constant.BaseBoConstants; import com.todoitbo.tallybookdasmart.exception.BusinessException; import io.minio.*; import io.minio.messages.Bucket; import io.minio.messages.Item; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.util.*; /** * @author xiaobo * @date 2023/5/21 */ @Component public class MinioUtil { private static MinioClient minioClient; @Autowired public void setMinioClient(MinioClient minioClient) { MinioUtil.minioClient = minioClient; } /** * description: 文件上传 * * @param bucketName 桶名称 * @param file 文件 * @param fileName 文件名 * @author bo * @date 2023/5/21 13:06 */ public static String upload(String bucketName, MultipartFile file, String fileName) { // 返回客户端文件系统中的原始文件名 String originalFilename = file.getOriginalFilename(); InputStream inputStream = null; try { inputStream = file.getInputStream(); minioClient.putObject(PutObjectArgs.builder() .bucket(bucketName) .object(fileName) .stream(inputStream, file.getSize(), -1) .build()); return bucketName + "/" + fileName; } catch (Exception e) { throw new BusinessException("文件上传失败:", e.getMessage()).setCause(e).setLog(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * description: 文件删除 * * @author bo * @date 2023/5/21 11:34 */ public static boolean delete(String bucketName, String fileName) { try { minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName) .object(fileName).build()); return BaseBoConstants.TRUE; } catch (Exception e) { throw new BusinessException("Minio文件删除失败", e.getMessage()).setCause(e).setLog(); } } /** * description: 删除桶 * * @param bucketName 桶名称 * @author bo * @date 2023/5/21 11:30 */ public static boolean removeBucket(String bucketName) { try { List folderList = getFolderList(bucketName); List fileNames = new ArrayList(); if (!folderList.isEmpty()) { for (Object value : folderList) { Map o = (Map) value; String name = (String) o.get("fileName"); fileNames.add(name); } } if (!fileNames.isEmpty()) { for (String fileName : fileNames) { delete(bucketName, fileName); } } minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); return BaseBoConstants.TRUE; } catch (Exception e) { throw new BusinessException("Minio删除桶失败:", e.getMessage()).setCause(e).setLog(); } } /** * description: 获取桶下所有文件的文件名+大小 * * @param bucketName 桶名称 * @author bo * @date 2023/5/21 11:39 */ public static List getFolderList(String bucketName) throws Exception { Iterable results = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build()); Iterator iterator = results.iterator(); List items = new ArrayList(); String format = "{'fileName':'%s','fileSize':'%s'}"; while (iterator.hasNext()) { Item item = iterator.next().get(); items.add(JSON.parse((String.format(format, item.objectName(), formatFileSize(item.size()))))); } return items; } /** * description: 格式化文件大小 * * @param fileS 文件的字节长度 * @author bo * @date 2023/5/21 11:40 */ private static String formatFileSize(long fileS) { DecimalFormat df = new DecimalFormat("#.00"); String fileSizeString = ""; String wrongSize = "0B"; if (fileS == 0) { return wrongSize; } if (fileS


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3