今天哥们又接到一个文件处理的开发需求,要实现一个文件上传、下载的通用服务。为了快速满足这一需求,我使用了SpringBoot
+ 华为云OBS
快速写了一个小小的程序。
项目结构如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| src └── main ├── java │ └── com │ └── xmbc │ └── file │ ├── XmbcFileApplication.java │ ├── config │ │ ├── HuaweiObsConfig.java │ │ └── ResourcesConfig.java │ ├── controller │ │ ├── HuaweiObsFileController.java │ │ └── SysFileController.java │ ├── service │ │ ├── ISysFileService.java │ │ └── impl │ │ ├── FastDfsSysFileServiceImpl.java │ │ ├── HuaweiObsSysFileServiceImpl.java │ │ └── LocalSysFileServiceImpl.java │ └── utils │ └── FileUploadUtils.java └── resources ├── application-dev.yaml ├── application-local.yaml ├── banner.txt ├── bootstrap.yaml └── logback.xml 12 directories, 15 files
|
好吧,大佬一看就知道这是使用了某个开源的框架,本文使用了若依的框架(对应ruoyi-file)。因为本文作者是个程序菜鸟,为了快速满足开发组长的需求,所以使用起来比较粗糙。
首先,看看我做了什么好事。在bootstrap.yaml
和application-local.yaml
中配置好参数,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| spring: profiles: active: local
server: port: 9300 spring: profiles: activate: on-profile: local application: name: xmbc-file cloud: nacos: discovery: enabled: false obs: huawei: bucketName: test-xcmg-app-fileprocessing endPoint: https://obs.cn-east-3.myhuaweicloud.com
file: path: "/" prefix: "xmbc_file" domain: "local.xmbc.com"
|
启动配置完成之后,我们就根据我上文的目录结构后注释的编号来看看对应的代码:
(1) HuaweiObsConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| 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;
@Configuration @ConfigurationProperties(prefix = "obs") @Data public class HuaweiObsConfig {
@Value("${obs.huawei.endPoint}") String endPoint;
private String accessKey = System.getenv("HUAWEICLOUD_SDK_AK");
private String secretKey = System.getenv("HUAWEICLOUD_SDK_SK");
@Value("${obs.huawei.bucketName}") private String bucketName;
@Bean public ObsClient getHuaweiObsClient() { return new ObsClient(accessKey, secretKey,endPoint); } }
|
(2) ISysFileService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.xmbc.file.service;
import org.springframework.core.io.InputStreamResource; import org.springframework.web.multipart.MultipartFile;
public interface ISysFileService {
public String uploadFile(MultipartFile file) throws Exception;
public InputStreamResource downloadFile(String fileName) throws Exception; }
|
(3) HuaweiObsSysFileServiceImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| 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;
@Service(value = "huaweiObsSysFileService") public class HuaweiObsSysFileServiceImpl implements ISysFileService { @Autowired private HuaweiObsConfig huaweiObsConfig;
@Autowired private ObsClient huaweiObsClient;
@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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| 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;
@RestController public class HuaweiObsFileController { private static final Logger log = LoggerFactory.getLogger(HuaweiObsFileController.class);
@Autowired @Qualifier("huaweiObsSysFileService") private ISysFileService huaweiObsSysFileService;
@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()); } }
@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())); } } }
|