项目中使用到的类库:spark-md5
、axios
、element-ui
;
npm install spark-md5 --S
npm install axios --S
上传示例
文件上传任务数:{{ taskQueueRunningNum }}
选择文件
上传
清空
{{
isPaused ? '继续' : '暂停'
}}
{{ item.name }}
{{ transformByte(item.size) || item.size }}
{{ `${item.uploadSpeed ? item.uploadSpeed : 0} M/s` }}
等待上传
校验MD5
正在创建序列
正在上传
上传完成
上传错误
框架封装的请求,可以根据使用的框架自己改一下,就是请求后台接口
import request from '@/utils/request'
//上传信息
export function uploadFileInfo(data){
return request({
url:'upload/multipart/uploadFileInfo',
method:'post',
data
})
}
// 上传校验
export function checkUpload(MD5) {
return request({
url: `upload/multipart/check?md5=${MD5}`,
method: 'get',
})
};
// 初始化上传
export function initUpload(data) {
return request({
url: `upload/multipart/init`,
method: 'post',
data
})
};
// 文件合并
export function mergeUpload(data) {
return request({
url: `upload/multipart/merge`,
method: 'post',
data
})
};
//判断文件是否存在
export function fileIsExits(data) {
return request({
url: `upload/multipart/fileIsExits`,
method: 'post',
data
})
};
框架内容,自行修改
import axios from 'axios'
// 创建 axios 实例
const service = axios.create({
baseURL: "/api", // 环境的不同,对应不同的baseURL
// transformRequest: [function(data) {
// return Qs.stringify(data)
// }],
//timeout: 5000 // 请求超时时间
})
//request请求拦截
service.interceptors.request.use(
config => {
// var token=getToken()
// if (token) {
// config.headers.token = token // 让每个请求携带自定义token 请根据实际情况自行修改
// }
return config;
},
error => {
// do something with request error
return Promise.reject(error)
}
)
//响应拦截
service.interceptors.response.use(
response => {
const res = response
return res
},
error => {
//这里还可以根据实际情况增加一些功能
return Promise.reject(error)
}
)
export default service
后端使用的是springboot ,使用之前要启动minio,redis,否则文件上传会出现异常。这里我都是使用windows版的
package com.xy.fileservice.controller;
import com.xy.fileservice.entity.FileUploadInfo;
import com.xy.fileservice.service.UploadService;
import com.xy.fileservice.util.MinioUtils;
import com.xy.fileservice.util.ResponseResult;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
* minio上传流程
*
* 1.检查数据库中是否存在上传文件
*
* 2.根据文件信息初始化,获取分片预签名url地址,前端根据url地址上传文件
*
* 3.上传完成后,将分片上传的文件进行合并
*
* 4.保存文件信息到数据库
*/
@Slf4j
@RestController
@RequestMapping("/upload")
public class FileMinioController {
@Resource
private UploadService uploadService;
@Resource
private MinioUtils minioUtils;
/**
* 校验文件是否存在
*
* @param md5 String
* @return ResponseResult
package com.xy.fileservice.service;
import com.xy.fileservice.entity.FileUploadInfo;
import com.xy.fileservice.util.ResponseResult;
import org.springframework.web.multipart.MultipartFile;
public interface UploadService {
/**
* 分片上传初始化
*
* @param fileUploadInfo
* @return Map
*/
ResponseResult initMultiPartUpload(FileUploadInfo fileUploadInfo);
/**
* 完成分片上传
*
* @param fileUploadInfo
* @return boolean
*/
ResponseResult mergeMultipartUpload(FileUploadInfo fileUploadInfo);
/**
* 通过 sha256 获取已上传的数据
* @param sha256 String
* @return Mono
package com.xy.fileservice.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.xy.fileservice.entity.FileUploadInfo;
import com.xy.fileservice.service.UploadService;
import com.xy.fileservice.util.MinioUtils;
import com.xy.fileservice.util.RedisRepo;
import com.xy.fileservice.util.ResponseResult;
import com.xy.fileservice.util.ResultCode;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.util.Objects;
import static com.xy.fileservice.util.ResultCode.ACCESS_PARAMETER_INVALID;
@Slf4j
@Service
public class UploadServiceImpl implements UploadService {
@Resource
private MinioUtils fileService;
@Resource
private RedisRepo redisRepo;
/**
* 通过 md5 获取已上传的数据(断点续传)
*
* @param md5 String
* @return Mono
package com.xy.fileservice.util;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.HashMultimap;
import com.xy.fileservice.config.CustomMinioClient;
import com.xy.fileservice.entity.FileUploadInfo;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Part;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static com.xy.fileservice.util.ResultCode.DATA_NOT_EXISTS;
import static com.xy.fileservice.util.ResultCode.UPLOAD_FILE_FAILED;
@Slf4j
@Component
public class MinioUtils {
@Value(value = "${minio.endpoint}")
private String endpoint;
@Value(value = "${minio.accesskey}")
private String accesskey;
@Value(value = "${minio.secretkey}")
private String secretkey;
@Resource
private RedisRepo redisRepo;
private CustomMinioClient customMinioClient;
/**
* 用spring的自动注入会注入失败
*/
@PostConstruct
public void init() {
MinioClient minioClient = MinioClient.builder()
.endpoint(endpoint)
.credentials(accesskey, secretkey)
.build();
customMinioClient = new CustomMinioClient(minioClient);
}
/**
* 单文件签名上传
*
* @param objectName 文件全路径名称
* @param bucketName 桶名称
* @return /
*/
public ResponseResult getUploadObjectUrl(String objectName, String bucketName) {
log.info("tip message: 通过 <{}-{}> 开始单文件上传", objectName, bucketName);
try {
String url = getPresidedObjectUrl(bucketName, objectName);
Map resMap = new HashMap<>();
resMap.put("uploadId", "SingleFileUpload");
resMap.put("urlList", Collections.singletonList(url));
return ResponseResult.success(resMap);
} catch (Exception e) {
log.error("error message: 初始化分片上传失败、原因:", e);
// 返回 文件上传失败
return ResponseResult.error(UPLOAD_FILE_FAILED);
}
}
/**
* 文件分片上传
*
* @param fileUploadInfo
* @param objectName 文件全路径名称
* @param partCount 分片数量
* @param contentType 类型,如果类型使用默认流会导致无法预览
* @param bucketName 桶名称
* @return Mono>
*/
public ResponseResult initMultiPartUpload(FileUploadInfo fileUploadInfo, String objectName, int partCount, String contentType, String bucketName) {
log.info("tip message: 通过 <{}-{}-{}-{}> 开始初始化<分片上传>数据", objectName, partCount, contentType, bucketName);
try {
String uploadId = getUploadId(bucketName, objectName, contentType);
fileUploadInfo.setUploadId(uploadId);
//redis保存文件信息
redisRepo.saveTimeout(fileUploadInfo.getFileMd5(), JSONObject.toJSONString(fileUploadInfo), 30, TimeUnit.MINUTES);
List partList = getPartUploadUrls(uploadId, partCount, bucketName, objectName);
Map resMap = new HashMap<>();
resMap.put("uploadId", uploadId);
resMap.put("urlList", partList);
log.info("tip message: 文件初始化<分片上传>、成功");
return ResponseResult.success(resMap);
} catch (Exception e) {
log.error("error message: 初始化分片上传失败、原因:", e);
// 返回 文件上传失败
return ResponseResult.error(UPLOAD_FILE_FAILED);
}
}
/**
* 分片上传完后合并
*
* @param objectName 文件全路径名称
* @param uploadId 返回的uploadId
* @param bucketName 桶名称
* @return boolean
*/
public boolean mergeMultipartUpload(String objectName, String uploadId, String bucketName) {
try {
log.info("tip message: 通过 <{}-{}-{}> 合并<分片上传>数据", objectName, uploadId, bucketName);
//目前仅做了最大1000分片
Part[] parts = new Part[1000];
// 查询上传后的分片数据
ListPartsResponse partResult = customMinioClient.listMultipart(bucketName, null, objectName, 1000, 0, uploadId, null, null);
int partNumber = 1;
for (Part part : partResult.result().partList()) {
parts[partNumber - 1] = new Part(partNumber, part.etag());
partNumber++;
}
// 合并分片
customMinioClient.mergeMultipartUpload(bucketName, null, objectName, uploadId, parts, null, null);
} catch (Exception e) {
log.error("error message: 合并失败、原因:", e);
return false;
}
return true;
}
/**
* 通过 sha256 获取上传中的分片信息
*
* @param objectName 文件全路径名称
* @param uploadId 返回的uploadId
* @param bucketName 桶名称
* @return Mono>
*/
public ResponseResult getByFileMd5(String objectName, String uploadId, String bucketName) {
log.info("通过 <{}-{}-{}> 查询上传分片数据", objectName, uploadId, bucketName);
try {
// 查询上传后的分片数据
ListPartsResponse partResult = customMinioClient.listMultipart(bucketName, null, objectName, 1000, 0, uploadId, null, null);
List collect = partResult.result().partList().stream().map(Part::partNumber).collect(Collectors.toList());
return ResponseResult.uploading(collect);
} catch (Exception e) {
log.error("error message: 查询上传后的分片信息失败、原因:", e);
return ResponseResult.error(DATA_NOT_EXISTS);
}
}
/**
* 获取文件下载地址
*
* @param bucketName 桶名称
* @param fileName 文件名
* @return
*/
public String getFilePath(String bucketName, String fileName) {
return StrUtil.format("{}/{}/{}", endpoint, bucketName, fileName);//文件访问路径
}
/**
* 创建一个桶
*
* @return
*/
public String createBucket(String bucketName) {
try {
BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();
//如果桶存在
if (customMinioClient.bucketExists(bucketExistsArgs)) {
return bucketName;
}
// 如果不存在则创建新文件桶
MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
customMinioClient.makeBucket(makeBucketArgs);
return bucketName;
} catch (Exception e) {
log.error("创建桶失败:{}", e.getMessage());
throw new RuntimeException(e);
}
}
/**
* 根据文件类型获取minio桶名称
*
* @param fileType
* @return
*/
public String getBucketName(String fileType) {
try {
if (StringUtils.isNotEmpty(fileType)) {
//判断桶是否存在
String bucketName = createBucket(fileType.toLowerCase());
if (StringUtils.isNotEmpty(bucketName)) {
return bucketName;
} else {
return fileType;
}
}
} catch (Exception e) {
log.error("Error reading bucket name ");
}
return fileType;
}
/**
* 单文件获取上传url
* @param bucketName
* @param objectName
* @return
* @throws ServerException
* @throws InsufficientDataException
* @throws ErrorResponseException
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws XmlParserException
* @throws InternalException
*/
private String getPresidedObjectUrl(String bucketName, String objectName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
return customMinioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(bucketName)
.object(objectName)
.expiry(1, TimeUnit.DAYS)
.build());
}
/**
* 获取合并id
* @param bucketName
* @param objectName
* @param contentType
* @return
* @throws ServerException
* @throws InsufficientDataException
* @throws ErrorResponseException
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws XmlParserException
* @throws InvalidResponseException
* @throws InternalException
*/
private String getUploadId(String bucketName, String objectName, String contentType) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, XmlParserException, InvalidResponseException, InternalException {
if (CharSequenceUtil.isBlank(contentType)) {
contentType = "application/octet-stream";
}
HashMultimap headers = HashMultimap.create();
headers.put("Content-Type", contentType);
return customMinioClient.initMultiPartUpload(bucketName, null, objectName, headers, null);
}
/**
* 获取文件分片urls
* @param uploadId
* @param partCount
* @param bucketName
* @param objectName
* @return
* @throws ServerException
* @throws InsufficientDataException
* @throws ErrorResponseException
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws XmlParserException
* @throws InternalException
*/
private List getPartUploadUrls(String uploadId, int partCount, String bucketName, String objectName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
List partList = new ArrayList<>();
for (int i = 1; i <= partCount; i++) {
Map reqParams = new HashMap<>();
reqParams.put("uploadId", uploadId);
reqParams.put("partNumber", String.valueOf(i));
String uploadUrl = customMinioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(bucketName)
.object(objectName)
.expiry(1, TimeUnit.DAYS)
.extraQueryParams(reqParams)
.build());
partList.add(uploadUrl);
}
return partList;
}
/**
* 判断文件是否存在
*
* @param bucketName 存储桶
* @param objectName 对象
* @return true:存在
*/
public boolean doesObjectExist(String bucketName, String objectName) {
boolean exist = true;
try {
customMinioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
} catch (Exception e) {
exist = false;
}
return exist;
}
/**
* 文件上传
*
* @param file 文件
* @return Boolean
*/
public String upload(MultipartFile file, String bucketName) {
String originalFilename = file.getOriginalFilename();
if (StringUtils.isBlank(originalFilename)) {
throw new RuntimeException();
}
String objectName = file.getName();
try {
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(objectName)
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
//文件名称相同会覆盖
customMinioClient.putObject(objectArgs);
} catch (Exception e) {
e.printStackTrace();
return null;
}
// 查看文件地址
GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(bucketName).object(objectName).method(Method.GET).build();
String url = null;
try {
url = customMinioClient.getPresignedObjectUrl(build);
} catch (ErrorResponseException e) {
e.printStackTrace();
} catch (InsufficientDataException e) {
e.printStackTrace();
} catch (InternalException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (XmlParserException e) {
e.printStackTrace();
} catch (ServerException e) {
e.printStackTrace();
}
return url;
}
}
package com.xy.config;
import com.google.common.collect.Multimap;
import io.minio.CreateMultipartUploadResponse;
import io.minio.ListPartsResponse;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.errors.*;
import io.minio.messages.Part;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class CustomMinioClient extends MinioClient {
/**
* 继承父类
* @param client
*/
public CustomMinioClient(MinioClient client) {
super(client);
}
/**
* 初始化分片上传、获取 uploadId
*
* @param bucket String 存储桶名称
* @param region String
* @param object String 文件名称
* @param headers Multimap 请求头
* @param extraQueryParams Multimap
* @return String
*/
public String initMultiPartUpload(String bucket, String region, String object, Multimap headers, Multimap extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException {
CreateMultipartUploadResponse response = this.createMultipartUpload(bucket, region, object, headers, extraQueryParams);
return response.result().uploadId();
}
/**
* 合并分片
*
* @param bucketName String 桶名称
* @param region String
* @param objectName String 文件名称
* @param uploadId String 上传的 uploadId
* @param parts Part[] 分片集合
* @param extraHeaders Multimap
* @param extraQueryParams Multimap
* @return ObjectWriteResponse
*/
public ObjectWriteResponse mergeMultipartUpload(String bucketName, String region, String objectName, String uploadId, Part[] parts, Multimap extraHeaders, Multimap extraQueryParams) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, ServerException, InternalException, XmlParserException, InvalidResponseException, ErrorResponseException {
return this.completeMultipartUpload(bucketName, region, objectName, uploadId, parts, extraHeaders, extraQueryParams);
}
/**
* 查询当前上传后的分片信息
*
* @param bucketName String 桶名称
* @param region String
* @param objectName String 文件名称
* @param maxParts Integer 分片数量
* @param partNumberMarker Integer 分片起始值
* @param uploadId String 上传的 uploadId
* @param extraHeaders Multimap
* @param extraQueryParams Multimap
* @return ListPartsResponse
*/
public ListPartsResponse listMultipart(String bucketName, String region, String objectName, Integer maxParts, Integer partNumberMarker, String uploadId, Multimap extraHeaders, Multimap extraQueryParams) throws NoSuchAlgorithmException, InsufficientDataException, IOException, InvalidKeyException, ServerException, XmlParserException, ErrorResponseException, InternalException, InvalidResponseException {
return this.listParts(bucketName, region, objectName, maxParts, partNumberMarker, uploadId, extraHeaders, extraQueryParams);
}
}
corsConf
框架自带可不用
package com.xy.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 全局跨域处理
* @author CV
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setMaxAge(3600L);
corsConfiguration.setAllowCredentials(true);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
package com.xy.util;
import lombok.Data;
@Data
public class ResponseResult {
private int code;
private String enMessage;
private String zhMessage;
private T data;
public ResponseResult() {
}
public ResponseResult(int code, String enMessage, String zhMessage) {
this.code = code;
this.enMessage = enMessage;
this.zhMessage = zhMessage;
}
/**
* 成功
*/
public static ResponseResult success() {
ResponseResult result = new ResponseResult();
result.setCode(ResultCode.SUCCESS.getCode());
result.setEnMessage(ResultCode.SUCCESS.getEnMessage());
result.setZhMessage(ResultCode.SUCCESS.getZhMessage());
return result;
}
/**
* 成功
*/
public static ResponseResult success(T data) {
ResponseResult result = new ResponseResult();
result.setCode(ResultCode.SUCCESS.getCode());
result.setEnMessage(ResultCode.SUCCESS.getEnMessage());
result.setZhMessage(ResultCode.SUCCESS.getZhMessage());
result.setData(data);
return result;
}
/**
* 失败
*/
public static ResponseResult error() {
ResponseResult result = new ResponseResult();
result.setCode(ResultCode.FAIL.getCode());
result.setEnMessage(ResultCode.FAIL.getEnMessage());
result.setZhMessage(ResultCode.FAIL.getZhMessage());
return result;
}
/**
* 失败
*/
public static ResponseResult error(T data) {
ResponseResult result = new ResponseResult();
result.setCode(ResultCode.FAIL.getCode());
result.setEnMessage(ResultCode.FAIL.getEnMessage());
result.setZhMessage(ResultCode.FAIL.getZhMessage());
result.setData(data);
return result;
}
/**
*
* @param data 数据
* @param
* @return
*/
public static ResponseResult uploading(T data) {
ResponseResult result = new ResponseResult();
result.setCode(ResultCode.UPLOADING.getCode());
result.setEnMessage(ResultCode.UPLOADING.getEnMessage());
result.setZhMessage(ResultCode.UPLOADING.getZhMessage());
result.setData(data);
return result;
}
/**
* 成功
*/
public static ResponseResult success(int code, String enMessage, String zhMessage) {
return new ResponseResult(code, enMessage, zhMessage);
}
/**
* 失败
*/
public static ResponseResult error(int code, String enMessage, String zhMessage) {
return new ResponseResult(code, enMessage, zhMessage);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getEnMessage() {
return enMessage;
}
public void setEnMessage(String enMessage) {
this.enMessage = enMessage;
}
public String getZhMessage() {
return zhMessage;
}
public void setZhMessage(String zhMessage) {
this.zhMessage = zhMessage;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
// public static ResponseResult SUCCESS = new ResponseResult<>(200,"成功");
// public static ResponseResult INTEVER_ERROR = new ResponseResult<>(500,"服务器错误");
// public static ResponseResult NOT_FOUND = new ResponseResult<>(404,"未找到");
}
package com.xy.util;
/**
* http状态码枚举类
*/
public enum ResultCode {
SUCCESS(1, "Success", "成功"),
UPLOADING(2, "Uploading", "上传中"),
FAIL(-1, "Err", "失败"),
DATABASE_OPERATION_FAILED(504, "数据库操作失败"),
CONTINUE(100, "Continue", "请继续发送请求的剩余部分"),
SWITCHING_PROTOCOLS(101, "Switching Protocols", "协议切换"),
PROCESSING(102, "Processing", "请求将继续执行"),
CHECKPOINT(103, "Checkpoint", "可以预加载"),
OK(200, "OK", "请求已经成功处理"),
CREATED(201, "Created", "请求已经成功处理,并创建了资源"),
ACCEPTED(202, "Accepted", "请求已经接受,等待执行"),
NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information", "请求已经成功处理,但是信息不是原始的"),
NO_CONTENT(204, "No Content", "请求已经成功处理,没有内容需要返回"),
RESET_CONTENT(205, "Reset Content", "请求已经成功处理,请重置视图"),
PARTIAL_CONTENT(206, "Partial Content", "部分Get请求已经成功处理"),
MULTI_STATUS(207, "Multi-Status", "请求已经成功处理,将返回XML消息体"),
ALREADY_REPORTED(208, "Already Reported", "请求已经成功处理,一个DAV的绑定成员被前一个请求枚举,并且没有被再一次包括"),
IM_USED(226, "IM Used", "请求已经成功处理,将响应一个或者多个实例"),
MULTIPLE_CHOICES(300, "Multiple Choices", "提供可供选择的回馈"),
MOVED_PERMANENTLY(301, "Moved Permanently", "请求的资源已经永久转移"),
FOUND(302, "Found", "请重新发送请求"),
SEE_OTHER(303, "See Other", "请以Get方式请求另一个URI"),
NOT_MODIFIED(304, "Not Modified", "资源未改变"),
USE_PROXY(305, "Use Proxy", "请通过Location域中的代理进行访问"),
TEMPORARY_REDIRECT(307, "Temporary Redirect", "请求的资源临时从不同的URI响应请求"),
RESUME_INCOMPLETE(308, "Resume Incomplete", "请求的资源已经永久转移"),
BAD_REQUEST(400, "Bad Request", "请求错误,请修正请求"),
UNAUTHORIZED(401, "Unauthorized", "没有被授权或者授权已经失效"),
PAYMENT_REQUIRED(402, "Payment Required", "预留状态"),
FORBIDDEN(403, "Forbidden", "请求被理解,但是拒绝执行"),
NOT_FOUND(404, "Not Found", "资源未找到"),
METHOD_NOT_ALLOWED(405, "Method Not Allowed", "请求方法不允许被执行"),
NOT_ACCEPTABLE(406, "Not Acceptable", "请求的资源不满足请求者要求"),
PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required", "请通过代理进行身份验证"),
REQUEST_TIMEOUT(408, "Request Timeout", "请求超时"),
CONFLICT(409, "Conflict", "请求冲突"),
GONE(410, "Gone", "请求的资源不可用"),
LENGTH_REQUIRED(411, "Length Required", "Content-Length未定义"),
PRECONDITION_FAILED(412, "Precondition Failed", "不满足请求的先决条件"),
REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large", "请求发送的实体太大"),
REQUEST_URI_TOO_LONG(414, "Request-URI Too Long", "请求的URI超长"),
UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type", "请求发送的实体类型不受支持"),
REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested range not satisfiable", "Range指定的范围与当前资源可用范围不一致"),
EXPECTATION_FAILED(417, "Expectation Failed", "请求头Expect中指定的预期内容无法被服务器满足"),
UNPROCESSABLE_ENTITY(422, "Unprocessable Entity", "请求格式正确,但是由于含有语义错误,无法响应"),
LOCKED(423, "Locked", "当前资源被锁定"),
FAILED_DEPENDENCY(424, "Failed Dependency", "由于之前的请求发生错误,导致当前请求失败"),
UPGRADE_REQUIRED(426, "Upgrade Required", "客户端需要切换到TLS1.0"),
PRECONDITION_REQUIRED(428, "Precondition Required", "请求需要提供前置条件"),
TOO_MANY_REQUESTS(429, "Too Many Requests", "请求过多"),
REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large", "请求头超大,拒绝请求"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error", "服务器内部错误"),
NOT_IMPLEMENTED(501, "Not Implemented", "服务器不支持当前请求的部分功能"),
BAD_GATEWAY(502, "Bad Gateway", "响应无效"),
SERVICE_UNAVAILABLE(503, "Service Unavailable", "服务器维护或者过载,拒绝服务"),
GATEWAY_TIMEOUT(504, "Gateway Timeout", "上游服务器超时"),
HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version not supported", "不支持的HTTP版本"),
VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates", "服务器内部配置错误"),
INSUFFICIENT_STORAGE(507, "Insufficient Storage", "服务器无法完成存储请求所需的内容"),
LOOP_DETECTED(508, "Loop Detected", "服务器处理请求时发现死循环"),
BANDWIDTH_LIMIT_EXCEEDED(509, "Bandwidth Limit Exceeded", "服务器达到带宽限制"),
NOT_EXTENDED(510, "Not Extended", "获取资源所需的策略没有被满足"),
NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required", "需要进行网络授权"),
ACCESS_PARAMETER_INVALID(1001,"Invalid access parameter","访问参数无效"),
UPLOAD_FILE_FAILED(1002,"File upload failure","文件上传失败"),
DATA_NOT_EXISTS(1003,"Data does not exist","数据不存在"),
;
private int code;
private String enMessage;
private String zhMessage;
ResultCode(int code, String enMessage, String zhMessage) {
this.code = code;
this.enMessage = enMessage;
this.zhMessage = zhMessage;
}
ResultCode(int code, String message) {
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getEnMessage() {
return enMessage;
}
public void setEnMessage(String enMessage) {
this.enMessage = enMessage;
}
public String getZhMessage() {
return zhMessage;
}
public void setZhMessage(String zhMessage) {
this.zhMessage = zhMessage;
}
}
package com.xy.entity;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class FileUploadInfo {
//@NotBlank(message = "文件名不能为空")
private String fileName;
// @NotNull(message = "文件大小不能为空")
private Double fileSize;
// @NotBlank(message = "Content-Type不能为空")
private String contentType;
// @NotNull(message = "分片数量不能为空")
private Integer partCount;
// @NotBlank(message = "uploadId 不能为空")
private String uploadId;
// 桶名称
//private String bucketName;
//md5
private String fileMd5;
//文件类型
private String fileType;
public FileUploadInfo() {
}
}
package com.xy.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component
public class RedisRepo {
@Autowired
private StringRedisTemplate redisTemplate;
public String get(String key) {
BoundValueOperations ops = redisTemplate.boundValueOps(key);
return ops.get();
}
public void save(String key,String str){
BoundValueOperations ops = redisTemplate.boundValueOps(key);
ops.set(str);
}
public void saveTimeout(String key, String value, long timeout, TimeUnit unit ){
redisTemplate.boundValueOps(key).setIfAbsent(value,timeout,unit);
}
public void delete(String key){
redisTemplate.delete(key);
}
public long expire(String key){
return redisTemplate.opsForValue().getOperations().getExpire(key);
}
}
minio:
endpoint: http://localhost:9000
accesskey: minioadmin
secretkey: minioadmin
spring:
redis:
host: localhost
port: 6379
io.minio
minio
8.3.1
com.squareup.okhttp3
okhttp
4.9.2
git地址: Study: study - Gitee.com
引用说明:
springboot整合Minio + vue 实现文件分片上传(完整代码已更新)_minioclient.putobject 方法如何获取上传进度-CSDN博客