2024-09-12-Thu-T-文件处理微服务
今天哥们又接到一个文件处理的开发需求,要实现一个文件上传、下载的通用服务。为了快速满足这一需求,我使用了SpringBoot + 华为云OBS快速写了一个小小的程序。
项目结构如下:
src
└── main
├── java
│ └── com
│ └── xmbc
│ └── file
│ ├── XmbcFileApplication.java # 启动类
│ ├── config
│ │ ├── HuaweiObsConfig.java # 华为云OBS的配置 (1)
│ │ └── ResourcesConfig.java
│ ├── controller
│ │ ├── HuaweiObsFileController.java # 文件上传下载的Controller (4)
│ │ └── SysFileController.java
│ ├── service
│ │ ├── ISysFileService.java # 文件处理的接口 (2)
│ │ └── impl
│ │ ├── FastDfsSysFileServiceImpl.java
│ │ ├── HuaweiObsSysFileServiceImpl.java # 华为云OBS的实现 (3)
│ │ └── LocalSysFileServiceImpl.java
│ └── utils
│ └── FileUploadUtils.java
└── resources
├── application-dev.yaml # 若依的框架原配置,没啥用,当个备份吧
├── application-local.yaml # 本地配置
├── banner.txt # 默认的logo
├── bootstrap.yaml # 启动类
└── logback.xml # 日志配置
12 directories, 15 files
好吧,大佬一看就知道这是使用了某个开源的框架,本文使用了若依的框架(对应ruoyi-file)。因为本文作者是个程序菜鸟,为了快速满足开发组长的需求,所以使用起来比较粗糙。
首先,看看我做了什么好事。在bootstrap.yaml和application-local.yaml中配置好参数,如下:
# bootstrap.yaml
spring:
profiles:
active: local
# application-local.yaml
server:
port: 9300
spring:
profiles:
activate:
on-profile: local
application:
name: xmbc-file
cloud:
nacos:
discovery:
enabled: false # 禁用nacos
obs:
huawei:
bucketName: test-xcmg-app-fileprocessing # 华为云OBS的bucket名称
endPoint: https://obs.cn-east-3.myhuaweicloud.com # 华为云OBS的endpoint
file: # 先随便乱写的,为了保证config可以读取,这里随便写一个。后续有需要再修改
path: "/"
prefix: "xmbc_file"
domain: "local.xmbc.com"
启动配置完成之后,我们就根据我上文的目录结构后注释的编号来看看对应的代码:
(1) HuaweiObsConfig.java
package com.xmbc.file.config;
import com.obs.services.ObsClient;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Minio 配置信息
*
* @author xmbc
*/
@Configuration
@ConfigurationProperties(prefix = "obs")
@Data
public class HuaweiObsConfig
{
/**
* endpoint填写桶所在的endpoint
*/
@Value("${obs.huawei.endPoint}")
String endPoint;
/**
* 华为云Access Key
*/
private String accessKey = System.getenv("HUAWEICLOUD_SDK_AK");
/**
* 华为云Secret Key
*/
private String secretKey = System.getenv("HUAWEICLOUD_SDK_SK");
/**
* 存储桶名称
*/
@Value("${obs.huawei.bucketName}")
private String bucketName;
/**
* 创建ObsClient实例
* 使用永久AK/SK初始化客户端
*/
@Bean
public ObsClient getHuaweiObsClient()
{
return new ObsClient(accessKey, secretKey,endPoint);
}
}
(2) ISysFileService.java
package com.xmbc.file.service;
import org.springframework.core.io.InputStreamResource;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件接口
*
* @author xmbc
*/
public interface ISysFileService
{
/**
* 文件上传接口
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
public String uploadFile(MultipartFile file) throws Exception;
/**
* 文件下载接口
*
* @param fileName 下载的文件
* @return 访问地址
* @throws Exception
*/
public InputStreamResource downloadFile(String fileName) throws Exception;
}
(3) HuaweiObsSysFileServiceImpl.java
package com.xmbc.file.service.impl;
import com.alibaba.nacos.common.utils.IoUtils;
import com.obs.services.ObsClient;
import com.obs.services.model.PutObjectRequest;
import com.obs.services.model.PutObjectResult;
import com.xmbc.file.config.HuaweiObsConfig;
import com.xmbc.file.service.ISysFileService;
import com.xmbc.file.utils.FileUploadUtils;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
/**
*文件存储
*
* @author xmbc
*/
@Service(value = "huaweiObsSysFileService")
public class HuaweiObsSysFileServiceImpl implements ISysFileService
{
@Autowired
private HuaweiObsConfig huaweiObsConfig;
@Autowired
private ObsClient huaweiObsClient;
/**
* Minio文件上传接口
*
* @param file 上传的文件
* @return 访问地址
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file) throws Exception
{
String fileName = FileUploadUtils.extractFilename(file);
InputStream inputStream = file.getInputStream();
PutObjectRequest request = new PutObjectRequest();
request.setBucketName(huaweiObsConfig.getBucketName());
request.setObjectKey(fileName);
request.setInput(inputStream);
PutObjectResult putObjectResult = huaweiObsClient.putObject(request);
IoUtils.closeQuietly(inputStream);
return putObjectResult.getObjectUrl();
}
@Override
public InputStreamResource downloadFile(String fileName) throws Exception {
return new InputStreamResource(huaweiObsClient.getObject(huaweiObsConfig.getBucketName(), fileName).getObjectContent());
}
}
(4) HuaweiObsController.java
package com.xmbc.file.controller;
import com.xmbc.common.core.domain.R;
import com.xmbc.common.core.utils.file.FileUtils;
import com.xmbc.file.service.ISysFileService;
import com.xmbc.system.api.domain.SysFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.Optional;
/**
* 文件请求处理
*
* @author xmbc
*/
@RestController
public class HuaweiObsFileController {
private static final Logger log = LoggerFactory.getLogger(HuaweiObsFileController.class);
@Autowired
@Qualifier("huaweiObsSysFileService")
private ISysFileService huaweiObsSysFileService;
/**
* 上传对象文件
* @param multipartFile
* @return
* @throws IOException
*/
@RequestMapping(value = "/uploadObject", method = {RequestMethod.POST, RequestMethod.PUT} , produces = MediaType.APPLICATION_JSON_VALUE)
public R<SysFile> uploadObject(@RequestParam("file") MultipartFile multipartFile) throws Exception {
try
{
// 上传并返回访问地址
String url = huaweiObsSysFileService.uploadFile(multipartFile);
SysFile sysFile = new SysFile();
sysFile.setName(FileUtils.getName(url));
sysFile.setUrl(url);
return R.ok(sysFile);
}
catch (Exception e)
{
log.error("上传文件失败", e);
return R.fail("上传文件失败: " + e.getMessage());
}
}
/**
* 下载对象文件
* @param fileName 文件名
* @return 文件对象
* @throws IOException
*/
@RequestMapping(value = "/downloadObject", method = {RequestMethod.GET} , produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity downloadObject(@RequestParam("fileName") String fileName, @RequestParam(value = "openStyle",required = false) String openStyle) throws Exception {
try
{
openStyle= "inline".equals(openStyle)?"inline":"attachment";
HttpHeaders headers = new HttpHeaders();
InputStreamResource inputStreamResource = huaweiObsSysFileService.downloadFile(fileName);
headers.add(HttpHeaders.CONTENT_DISPOSITION, openStyle + "; filename=" + fileName.substring(fileName.lastIndexOf('/')+1));
return ResponseEntity.ok()
.headers(headers)
.body(inputStreamResource);
}
catch (Exception e)
{
log.error("下载文件失败", e);
return ResponseEntity.of(Optional.of(e.getMessage()));
}
}
}

浙公网安备 33010602011771号