SpringBoot通过RestTemplate上传文件到Github
本文最后更新于 80 天前,其中的信息可能已经有所发展或是发生改变。

前言:

众所周知,Github仓库 + jsDelivr 可以做为全球加速的免费图床,上传图片可以使用Picgo,但是视频的话就不太方便了,如果能整合到自己的项目中,通过接口去上传图片/视频,那就会方便很多。



创建 public 仓库

首先需要在 Github 上创建一个开放的仓库

897195f5123110be20f67830f5325af636d89149.png



生成获取Access Token

接着需要在个人设置页面中生成 Access Token,生成的时候要记得复制下来保存,不然就看不到了。

ba40b6bb02331d2c741128bcf619d415f3a11f21_2_1035x343.png



SpringBoot 中 yml 文件添加如下配置:

 github:
   bucket:
     # 配置仓库所属的用户名(如果是自己创建的,就是自己的用户名)
     user: "springboot-community"
     # 配置仓库名称
     repository: "twitter-bucket"
     # 配置自己的acccessToken
     access-token: "996e748cb47117adbf3**********"
     url: "https://cdn.jsdelivr.net/gh/${github.bucket.user}/${github.bucket.repository}/"
     api: "https://api.github.com/repos/${github.bucket.user}/${github.bucket.repository}/contents/"

cdn.jsdelivr.net 是 jsDelivr 的官方加速节点,但是国内有屏蔽,加速效果不理想,可以换成国内的一些比较稳定的节点,我目前用的是 jsd.onmicrosoft.cn



封装文件上传工具类

如下代码是封装的一个工具类

主要特点是:

使用 UUID 重命名文件,防止冲突

根据日期打散目录,yyyy/mm/dd

 package com.wangyuan.utils;
 ​
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.gson.JsonPrimitive;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.*;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
 ​
 import javax.annotation.Resource;
 import java.io.IOException;
 import java.time.LocalDate;
 import java.util.*;
 ​
 ​
 @Component
 public class GithubUploader {
 ​
     private static final Logger LOGGER = LoggerFactory.getLogger(GithubUploader.class);
 ​
     public static final String URI_SEPARATOR = "/";
 ​
     public static final Set<String> ALLOW_FILE_SUFFIX = new HashSet<>(Arrays.asList("jpg", "png", "jpeg", "gif", "mp4"));
 ​
     @Value("${github.bucket.url}")
     private String url;
 ​
     @Value("${github.bucket.api}")
     private String api;
 ​
     @Value("${github.bucket.access-token}")
     private String accessToken;
 ​
     @Resource
     RestTemplate restTemplate;
 ​
     /**
      * 上传文件到Github
      *
      * @param multipartFile
      * @return 文件的访问地址
      * @throws IOException
      */
     public String upload(MultipartFile multipartFile) throws IOException {
 ​
         String suffix = this.getSuffix(multipartFile.getOriginalFilename()).toLowerCase();
         if (!ALLOW_FILE_SUFFIX.contains(suffix)) {
             throw new IllegalArgumentException("不支持的文件后缀:" + suffix);
         }
 ​
         // 重命名文件
         String fileName = UUID.randomUUID().toString().replace("-", "") + "." + suffix;
 ​
         // 目录按照日期打散
         String[] folders = this.getDateFolder();
 ​
         // 最终的文件路径
         String filePath = new StringBuilder(String.join(URI_SEPARATOR, folders)).append(fileName).toString();
 ​
         LOGGER.info("上传文件到Github:{}", filePath);
 ​
         JsonObject payload = new JsonObject();
         payload.add("message", new JsonPrimitive("file upload"));
         payload.add("content", new JsonPrimitive(Base64.getEncoder().encodeToString(multipartFile.getBytes())));
 ​
         HttpHeaders httpHeaders = new HttpHeaders();
         httpHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
         httpHeaders.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
         httpHeaders.set(HttpHeaders.AUTHORIZATION, "token " + this.accessToken);
 ​
         ResponseEntity<String> responseEntity = this.restTemplate.exchange(this.api + filePath, HttpMethod.PUT,
                 new HttpEntity<String>(payload.toString(), httpHeaders), String.class);
 ​
         if (responseEntity.getStatusCode().isError()) {
             // TODO 上传失败
         }
 ​
         JsonObject response = JsonParser.parseString(responseEntity.getBody()).getAsJsonObject();
 ​
         LOGGER.info("上传完毕: {}", response.toString());
 ​
 ​
         // TODO 序列化到磁盘备份
 ​
         return this.url + filePath;
     }
 ​
     /**
      * 获取文件的后缀
      *
      * @param fileName
      * @return
      */
     protected String getSuffix(String fileName) {
         int index = fileName.lastIndexOf(".");
         if (index != -1) {
             String suffix = fileName.substring(index + 1);
             if (!suffix.isEmpty()) {
                 return suffix;
             }
         }
         throw new IllegalArgumentException("非法的文件名称:" + fileName);
     }
 ​
     /**
      * 按照年月日获取打散的打散目录
      * yyyy/mmd/dd
      *
      * @return
      */
     protected String[] getDateFolder() {
         String[] retVal = new String[3];
 ​
         LocalDate localDate = LocalDate.now();
         retVal[0] = localDate.getYear() + "";
 ​
         int month = localDate.getMonthValue();
         retVal[1] = month < 10 ? "0" + month : month + "";
 ​
         int day = localDate.getDayOfMonth();
         retVal[2] = day < 10 ? "0" + day : day + "";
 ​
         return retVal;
     }
 }



调用工具类编写上传接口

最后就是在 Controller 层编写上传接口

 package com.wangyuan.controller;
 ​
 import com.wangyuan.common.Result;
 import com.wangyuan.utils.GithubUploader;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 ​
 import java.io.IOException;
 ​
 ​
 @CrossOrigin
 @RestController
 @RequestMapping("/file")
 public class FileController {
 ​
 ​
     @Autowired
     private GithubUploader githubUploader;
 ​
     /**
      * Github文件上传
      *
      * @param multipartFile
      * @return
      * @throws IOException
      */
     @PostMapping("/github/upload")
     public Object upload(@RequestParam(value = "file") MultipartFile multipartFile) throws IOException {
         return Result.success(this.githubUploader.upload(multipartFile));
     }
 }

上传成功后会返回一串访问的 URL



测试

这里使用 Apipost 进行测试

image.png

如图显示,测试成功~



参考资料

在SpringBoot中通过RestTemplate提交文件到Github(白嫖图床)_怎么springboot怎么把图片上传到github里面-CSDN博客

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇