专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

在SpringBoot中通过RestTemplate提交文件到Github(白嫖图床)

在SpringBoot中通过RestTemplate提交文件到Github(白嫖图床)

Github仓库 + jsDelivr = 全球加速的免费图床

之前写过一篇帖子,GitHub + jsDelivr CDN 全球加速的免费图床,它不香吗? 这篇帖子中,使用的是桌面客户端 PicGo,进行图片上传的。在这里我们使用SpringBoot中的RestTemplate作为客户端,上传文件到Github仓库。

先在Github中创建一个public的仓库,和AccessToken

参考上面的帖子,这里不再重复讲诉。

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/"

你只需要配置好,上面自己有注释的3个配置就OK了

GithubUploaderGithubUploader

封装的一个工具类,根据上面的配置进行文件的上传

  • 使用UUID重新命名文件,防止冲突
  • 根据日期打散目录:yyyy/mm/dd
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;

@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")); 

    @Value("${github.bucket.url}")
    private String url;

    @Value("${github.bucket.api}")
    private String api;

    @Value("${github.bucket.access-token}")
    private String accessToken;

    @Autowired
    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

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import io.springboot.twitter.common.Message;
import io.springboot.twitter.github.GithubUploader;

@RestController
@RequestMapping("/upload")
public class UploadController {

    @Autowired
    private GithubUploader githubUploader;

    @PostMapping
    public Object upload (@RequestParam("file") MultipartFile multipartFile) throws IOException {
        return Message.success(this.githubUploader.upload(multipartFile));
    }
}

测试OK

35_1.png

通过CDN访问上传后的文件

https://user-gold-cdn.xitu.io/2020/6/16/172bd76e6bd149f0?w=415&h=337&f=gif&s=2711243

35_2.png

文章永久链接:https://tech.souyunku.com/35587

未经允许不得转载:搜云库技术团队 » 在SpringBoot中通过RestTemplate提交文件到Github(白嫖图床)

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们