文件操作(1.文件资源上传到MinIO 2.文件资源保存在数据库中)

目录

本文提供文件操作接口的实现(上传+下载)

附件资源表实体类

具体代码实现

上传到MinIO服务器

pom依赖

yml配置

MinIO配置

服务实现类

保存到数据库


本文提供文件操作接口的实现(上传+下载)
附件资源表实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@TableName("attachment_info")
@ApiModel(value="AttachmentInfoEntity", description="附件资源表")
public class AttachmentInfoEntity extends BaseEntity<AttachmentInfoEntity> {


    @ApiModelProperty(value = "附件id")
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty(value = "关联id")
    @TableField("file_id")
    private String fileId;

    @ApiModelProperty(value = "关联业务模块(存储桶名)")
    @TableField("bucket_name")
    private String bucketName;

    @ApiModelProperty(value = "请求头文件类型")
    @TableField("content_type")
    private String contentType;

    @ApiModelProperty(value = "文件类型 默认 普通文件 file ,可选 电子签章 electronic_sign_file")
    @TableField("file_type")
    private String fileType;

    @ApiModelProperty(value = "文件名称")
    @TableField("file_name")
    private String fileName;

    @ApiModelProperty(value = "文件大小")
    @TableField("file_size")
    private BigDecimal fileSize;

    @ApiModelProperty(value = "文件存储路径")
    @TableField("file_path")
    private String filePath;

    @ApiModelProperty(value = "文件内容")
    @TableField("file_data")
    private byte[] fileData;

    @ApiModelProperty(value = "删除标识(0未删除/1已删除)")
    @TableField("is_delete")
    @TableLogic(value="0",delval="1")
    private Integer isDelete;


}
具体代码实现

controller层

@Api(tags = "文件操作相关接口")
@RestController
@RequestMapping("/file")
@Slf4j
public class FileStorageController {
    @Resource(name = "localFileStorageServiceImpl")
    private FileStorageService fileStorageService;

    @ApiOperation("上传文件")
    @PostMapping(value = "/upload")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "文件", required = true, dataType = "MultipartFile", paramType = "form"),
            @ApiImplicitParam(name = "bucketName", value = "桶名(以小写字母或数字开头和结尾,中间可以包含小写字母、数字、点(.)或短横线(-)的字符串)", required = true, dataType = "String", paramType = "form")
    })
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Object> upload(@RequestPart(value = "file") MultipartFile fileList, @RequestParam(value = "bucketName") String bucketName) {
        return fileStorageService.upload(fileList, bucketName);
    }


    @ApiOperation("下载指定的MinIO文件2")
    @GetMapping("view2")
    public void view2(@RequestParam("fileId") String fileId, HttpServletResponse httpServletResponse) {
        fileStorageService.download(fileId, httpServletResponse);
    }
}

service层

public interface FileStorageService {

    /**
     * 上传文件
     *
     * @param fileList   需要上传的文件
     * @param bucketName MinIo文件服务器桶名称(从枚举类中获取)
     * @return 上传成功之后保存到文档服务器上的文件名称
     */
    ApiResult<Object> upload(MultipartFile fileList, String bucketName);

    /**
     * 文件下载
     *
     * @param fileId 文件id
     */
    void download(String fileId, HttpServletResponse httpServletResponse);

}
上传到MinIO服务器
pom依赖
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.squareup.okhttp3</groupId>
                    <artifactId>okhttp</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.12.0</version>
        </dependency>
yml配置
minio:
  endpoint: http://10.10.xx.xxx:xxxx
  accesskey: admin
  secretkey: admin123
MinIO配置
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinIOInfo {
    // MinIo服务器地址
    private String endpoint;
    // MinIo服务器账号
    private String accesskey;
    // MinIo服务器密码
    private String secretkey;
}

@Configuration
public class MinIOConfiguration {

    @Resource
    private MinIOInfo minIOInfo;

    @Bean
    public MinioClient minioClient() {
        // 构建MinioClient对象
        return MinioClient.builder()
                .endpoint(minIOInfo.getEndpoint())
                .credentials(minIOInfo.getAccesskey(), minIOInfo.getSecretkey())
                .build();
    }
}

服务实现类
@Service
@Slf4j
@RequiredArgsConstructor
public class MinioFileStorageServiceImpl implements FileStorageService {

    private final MinioClient minioClient;
    private final AttachmentInfoService attachmentInfoService;

    private static final String FOLDER = "/usr/local/uploadFile/";

    /**
     * 将文件上传到指定的MinIO存储桶中
     *
     * @param file       要上传的文件
     * @param bucketName 存储桶名称
     * @return 返回上传到MinIO后保存的文件名
     * @throws Exception 如果上传过程中发生错误,则抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Object> upload(MultipartFile file, String bucketName) {
        try {
            log.info("开始上传文件,桶名:{}", bucketName);
            // 检查并创建存储桶(如果不存在)
            boolean exist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exist) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                log.info("创建存储桶:{}", bucketName);
            }

            // 获取文件原始名称和内容类型
            String orgName = file.getOriginalFilename();
            String contentType = file.getContentType();
            log.info("上传文件:文件名={}, 内容类型={}", orgName, contentType);

            // 检查文件名是否合法
            if (StringUtils.isEmpty(orgName) || orgName.contains("..")) {
                throw new BizException("文件名不合法,请检查上传的文件");
            }

            // 生成唯一文件名
            String fileName = DateUtil.current() + "." + StringUtils.substringAfterLast(orgName, ".");
            // 提取文件类型
            String fileType = StringUtils.substringAfterLast(orgName, ".");

            // 准备上传文件的参数和流
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .contentType(contentType)
                    .object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .build();

            // 上传文件到MinIO
            minioClient.putObject(putObjectArgs);

            log.info("文件已上传到 MinIO:存储桶={}, 文件名={}", bucketName, fileName);

            AttachmentInfoEntity attachmentInfo = new AttachmentInfoEntity()
                    .setFileId(IdUtil.simpleUUID())
                    .setFileName(orgName)
                    .setFilePath(fileName)
                    .setContentType(contentType)
                    .setBucketName(bucketName)
                    .setFileType(fileType)
                    .setFileSize(BigDecimal.valueOf(file.getSize()));

            attachmentInfoService.save(attachmentInfo);

            return ApiResult.success(attachmentInfo.getFileId());
        } catch (Exception e) {
            log.error("文件上传失败:{}", e.getMessage());
            return ApiResult.fail();
        }
    }


    /**
     * 从MinIO存储系统下载文件
     *
     * @param fileId 文件id
     */
    @Override
    public void download(String fileId, HttpServletResponse response) {
        try {
            log.info("开始下载文件,文件id为:{}", fileId);
            // 获取文件信息
            AttachmentInfoEntity attachment = attachmentInfoService.getAttachmentInfoByFileId(fileId);
            if (attachment == null) {
                throw new BizException("文件不存在,请检查文件ID");
            }
            // 检查存储桶是否存在
            String bucketName = attachment.getBucketName();
            boolean exist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exist) {
                throw new BizException("存储桶不存在:{}", bucketName);
            }
            // 设置响应头
            String fileName = attachment.getFileName();
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setCharacterEncoding("UTF-8");
            response.setContentType(attachment.getContentType());

            // 从 MinIO 下载文件
            String objectName = attachment.getFilePath();
            GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build();

            try (InputStream in = minioClient.getObject(getObjectArgs)) {
                IoUtil.copy(in, response.getOutputStream());
            }

            log.info("文件下载成功:文件ID={}, 存储桶={}, 文件名={}", fileId, bucketName, attachment.getFileName());
        } catch (Exception e) {
            log.error("文件下载服务器错误:{}", e.getMessage());
            throw new BizException("文件下载服务器错误");
        }
    }

}
保存到数据库
@Service
@Slf4j
@RequiredArgsConstructor
public class MinioFileStorageServiceImpl implements FileStorageService {

    private final MinioClient minioClient;
    private final AttachmentInfoService attachmentInfoService;

    private static final String FOLDER = "/usr/local/uploadFile/";

    /**
     * 将文件上传到指定的MinIO存储桶中
     *
     * @param file       要上传的文件
     * @param bucketName 存储桶名称
     * @return 返回上传到MinIO后保存的文件名
     * @throws Exception 如果上传过程中发生错误,则抛出异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Object> upload(MultipartFile file, String bucketName) {
        try {
            log.info("开始上传文件,桶名:{}", bucketName);
            // 检查并创建存储桶(如果不存在)
            boolean exist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exist) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                log.info("创建存储桶:{}", bucketName);
            }

            // 获取文件原始名称和内容类型
            String orgName = file.getOriginalFilename();
            String contentType = file.getContentType();
            log.info("上传文件:文件名={}, 内容类型={}", orgName, contentType);

            // 检查文件名是否合法
            if (StringUtils.isEmpty(orgName) || orgName.contains("..")) {
                throw new BizException("文件名不合法,请检查上传的文件");
            }

            // 生成唯一文件名
            String fileName = DateUtil.current() + "." + StringUtils.substringAfterLast(orgName, ".");
            // 提取文件类型
            String fileType = StringUtils.substringAfterLast(orgName, ".");

            // 准备上传文件的参数和流
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .contentType(contentType)
                    .object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .build();

            // 上传文件到MinIO
            minioClient.putObject(putObjectArgs);

            log.info("文件已上传到 MinIO:存储桶={}, 文件名={}", bucketName, fileName);

            AttachmentInfoEntity attachmentInfo = new AttachmentInfoEntity()
                    .setFileId(IdUtil.simpleUUID())
                    .setFileName(orgName)
                    .setFilePath(fileName)
                    .setContentType(contentType)
                    .setBucketName(bucketName)
                    .setFileType(fileType)
                    .setFileSize(BigDecimal.valueOf(file.getSize()));

            attachmentInfoService.save(attachmentInfo);

            return ApiResult.success(attachmentInfo.getFileId());
        } catch (Exception e) {
            log.error("文件上传失败:{}", e.getMessage());
            return ApiResult.fail();
        }
    }


    /**
     * 从MinIO存储系统下载文件
     *
     * @param fileId 文件id
     */
    @Override
    public void download(String fileId, HttpServletResponse response) {
        try {
            log.info("开始下载文件,文件id为:{}", fileId);
            // 获取文件信息
            AttachmentInfoEntity attachment = attachmentInfoService.getAttachmentInfoByFileId(fileId);
            if (attachment == null) {
                throw new BizException("文件不存在,请检查文件ID");
            }
            // 检查存储桶是否存在
            String bucketName = attachment.getBucketName();
            boolean exist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exist) {
                throw new BizException("存储桶不存在:{}", bucketName);
            }
            // 设置响应头
            String fileName = attachment.getFileName();
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setCharacterEncoding("UTF-8");
            response.setContentType(attachment.getContentType());

            // 从 MinIO 下载文件
            String objectName = attachment.getFilePath();
            GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build();

            try (InputStream in = minioClient.getObject(getObjectArgs)) {
                IoUtil.copy(in, response.getOutputStream());
            }

            log.info("文件下载成功:文件ID={}, 存储桶={}, 文件名={}", fileId, bucketName, attachment.getFileName());
        } catch (Exception e) {
            log.error("文件下载服务器错误:{}", e.getMessage());
            throw new BizException("文件下载服务器错误");
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

伏颜.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值