Springboot 一行程式碼實現文件上傳 20個平台!少寫程式碼到極致

大家好,我是小富~

又是做好人好事的一天,有個小可愛私下問我有沒有好用的springboot文件上傳工具,這不巧了嘛,正好我私藏了一個好東西,順便給小夥伴們也分享一下,demo地址放在文末了。

文件上傳在平常不過的一個功能,做後端開發的基本都會接觸到,雖然不難可著實有點繁瑣。數據流的開閉、讀取還容易出錯,尤其是在對接一些OSS對象存儲平台,一個平台一堆SDK程式碼看起來亂糟糟的。

下邊給我大家推薦一個工具Spring File Storage,上傳文件只要些許配置一行程式碼搞定,開發效率杠杠的,一起看看是不是有這麼流批!

官網://spring-file-storage.xuyanwu.cn

Spring File Storage工具幾乎整合了市面上所有的OSS對象存儲平台,包括本地FTPSFTPWebDAV阿里雲OSS華為雲OBS七牛雲Kodo騰訊雲COS百度雲 BOS又拍雲USSMinIO京東雲 OSS網易數帆 NOS等其它兼容 S3 協議的平台,只要在springboot中通過極簡的方式就可以實現文件存儲。

簡單配置

下邊以本地和Aliyun OSS上傳為例,pom.xml中引入必要的spring-file-storage.jar注意: 如果要上傳文件到OSS平台,需要引入對應平台的SDK包。

<!-- spring-file-storage 必須要引入 -->
<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.5.0</version>
</dependency>

<!-- 阿里雲oss -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>

application.yml文件中配置些基礎資訊。

  • enable-storage:只有狀態開啟才會被識別到
  • default-platform:默認的上傳平台
  • domain:生成的文件url中訪問的域名
  • base-path:存儲地址
  • thumbnail-suffix:縮略圖後綴

要是上傳OSS對象存儲平台,將aliyun oss提供的變數配置到相應的模組上即可。

spring:
  #文件存儲配置(本地、oss)
  file-storage:
    default-platform: local-1
    thumbnail-suffix: ".min.jpg" #縮略圖後綴
    local:
      - platform: local-1 # 存儲平台標識
        enable-storage: true #是否開啟本存儲(只能選一種)
        enable-access: true #啟用訪問(線上請使用 Nginx 配置,效率更高)
        domain: "//127.0.0.1:2222" #訪問域名,注意後面要和path-patterns保持一致,「/」結尾
        base-path: /tmp/Pictures/ # 存儲地址
        path-patterns: /** #訪問路徑
    aliyun-oss:
      - platform: aliyun-oss
        enable-storage: true
        access-key: xxxx
        secret-key: xxxx
        end-point: xxx
        bucket-name: firebook
        domain: //fire100.top
        base-path: #雲平台文件路徑

springboot啟動類中增加註解@EnableFileStorage,顯式的開啟文件上傳功能,到這就可以用了

@EnableFileStorage // 文件上傳工具
@SpringBootApplication
public class SpringbootFileStorageApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootFileStorageApplication.class, args);
    }
}

上傳文件

接下來在業務類中引入FileStorageService服務,如下只要一行程式碼就可以完成文件上傳,是不是So easy,下載也是如法炮製。

@RestController
public class FileController {

    @Autowired
    private FileStorageService fileStorageService;

    /**
     * 公眾號:程式設計師小富
     * 上傳文件
     */
    @PostMapping(value = {"/upload"})
    public Object upload(MultipartFile file) {
        FileInfo upload  = fileStorageService.of(file).upload();
        return upload;
    }
}

我們用postman測試上傳一張圖片,看到圖片已經成功傳到了/tmp/Pictures目錄下,返回結果中包含了完整的訪問文件的URL路徑。

不僅如此spring-file-storage還支援多種文件形式,URIURLStringbyte[]InputStreamMultipartFile,使開發更加靈活。

文件上傳功能,更多時候我們都是在上傳圖片,那就會有動態裁剪圖片生成縮略圖的需求,這些 spring-file-storage 都可以很容易實現。

/**
 * 公眾號:程式設計師小富
 * 上傳圖片裁剪大小並生成一張縮略圖
 */
@PostMapping("/uploadThumbnail")
public FileInfo uploadThumbnail(MultipartFile file) {
    return fileStorageService.of(file)
            .image(img -> img.size(1000,1000))  //將圖片大小調整到 1000*1000
            .thumbnail(th -> th.size(200,200))  //再生成一張 200*200 的縮略圖
            .upload();
}

而且我們還可以動態選擇上傳平台,配置文件中將所有平台開啟,在實際使用中自由的選擇。

/**
 * 公眾號:程式設計師小富
 * 上傳文件到指定存儲平台,成功返迴文件資訊
 */
@PostMapping("/upload-platform")
public FileInfo uploadPlatform(MultipartFile file) {
    return fileStorageService.of(file)
            .setPlatform("aliyun-oss")    //使用指定的存儲平台
            .upload();
}

下載文件

下載文件也同樣的簡單,可以直接根據文件url或者文件流下載。

/**
 * 公眾號:程式設計師小富
 * 下載文件
 */
@PostMapping("/download")
public void download(MultipartFile file) {
    // 獲取文件資訊
    FileInfo fileInfo = fileStorageService.getFileInfoByUrl("//file.abc.com/test/a.jpg");
    
    // 下載到文件
    fileStorageService.download(fileInfo).file("C:\\a.jpg");

    // 直接通過文件資訊中的 url 下載,省去手動查詢文件資訊記錄的過程
    fileStorageService.download("//file.abc.com/test/a.jpg").file("C:\\a.jpg");

    // 下載縮略圖
    fileStorageService.downloadTh(fileInfo).file("C:\\th.jpg");
}

提供了監聽下載進度的功能,可以清晰明了的掌握文件的下載情況。

// 下載文件 顯示進度
fileStorageService.download(fileInfo).setProgressMonitor(new ProgressListener() {
    @Override
    public void start() {
        System.out.println("下載開始");
    }

    @Override
    public void progress(long progressSize,long allSize) {
        System.out.println("已下載 " + progressSize + " 總大小" + allSize);
    }

    @Override
    public void finish() {
        System.out.println("下載結束");
    }
}).file("C:\\a.jpg");

文件存在、刪除

我們還可以根據文件的URL地址來判斷文件是否存在、以及刪除文件。

//直接通過文件資訊中的 url 刪除,省去手動查詢文件資訊記錄的過程
fileStorageService.delete("//file.abc.com/test/a.jpg");
//直接通過文件資訊中的 url 判斷文件是否存在,省去手動查詢文件資訊記錄的過程
boolean exists2 = fileStorageService.exists("//file.abc.com/test/a.jpg");

切面

工具還提供了每種操作的切面,可以在每個動作的前後進行干預,比如打日誌或者玩點花活,實現FileStorageAspect類重寫對應動作的xxxAround方法。

**
 * 使用切面列印文件上傳和刪除的日誌
 */
@Slf4j
@Component
public class LogFileStorageAspect implements FileStorageAspect {

    /**
     * 上傳,成功返迴文件資訊,失敗返回 null
     */
    @Override
    public FileInfo uploadAround(UploadAspectChain chain, FileInfo fileInfo, UploadPretreatment pre, FileStorage fileStorage, FileRecorder fileRecorder) {
        log.info("上傳文件 before -> {}",fileInfo);
        fileInfo = chain.next(fileInfo,pre,fileStorage,fileRecorder);
        log.info("上傳文件 after -> {}",fileInfo);
        return fileInfo;
    }
}

demo案例地址://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-file-storage

總結

用了這個工具確實極大的減少了上傳文件所帶來的程式碼量,提升了開發效率,使用過程中暫未發現有什麼坑,好東西就是要大家分享,如果符合你的需求,猶豫什麼用起來吧。

技術交流,公眾號:程式設計師小富