刚刚完成一个作业。涉及到图片的上传服务,因为自己经常会有一些图片管理的需求,七牛云,阿里云的oos存储又是付费的,所以自己根据GitHub的官方API搭建一个自己的图床服务。以便后续自己开发使用。
参考地址: GitHubAPI
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.mashape.unirest.http.exceptions.UnirestException;
import lombok.extern.slf4j.Slf4j;
import org.util.ErrorEnum;
import org.util.MyException;
import org.util.MyHttpUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class ImageUploadUtils {
public static String uploadImg(MultipartFile multipartFile) throws IOException, UnirestException {
String originalFilename = multipartFile.getOriginalFilename();
if(originalFilename == null){
throw new MyException(ErrorEnum.IMAGE_NOT_FOUND);
}
String targetURL = UploadGitHubImgBed.createUploadFileUrl(originalFilename);
log.info("目标url:"+targetURL);
//请求体封装
Map<String, Object> uploadBodyMap = UploadGitHubImgBed.getUploadBodyMap(multipartFile.getBytes());
Map<String, String> header = new HashMap<>();
// Github生成的token 参考GitHub API https://docs.github.com/cn/rest/reference/repos#create-or-update-file-contents
header.put("Authorization", "token 你的GitHub生成的token");
header.put("Accept", "application/vnd.github.v3+json");
header.put("Content-Type", "application/json");
//发送Put请求,这里只能用PUT请求
String JSONResult = MyHttpUtils.put(targetURL, uploadBodyMap, header);
//解析响应JSON字符串
//System.out.println(JSONResult);
JSONObject jsonObj = JSONUtil.parseObj(JSONResult);
//请求失败
if(jsonObj == null || jsonObj.getObj("commit") == null){
throw new MyException(ErrorEnum.IMAGE_FAIL_UPLOAD);
}
JSONObject content = JSONUtil.parseObj(jsonObj.getObj("content"));
String downloadUrl = (String)content.getObj("download_url");
log.info("上传到GitHub图床的地址:"+downloadUrl);
//请求成功:返回下载地址
return downloadUrl;
}
}
这里模拟http的Put请求是用的Unirest,这是一个非常好用的库,和python的requests库一样好用。
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import org.json.JSONObject;
import java.util.Map;
public class MyHttpUtils {
public static String put(String urlString, Map<String, Object> paramMap, Map<String,String> headers) throws UnirestException {
JSONObject jsonObject = new JSONObject(paramMap);
HttpResponse<String> response = Unirest.put(urlString).headers(headers)
.body(jsonObject).asString();
return response.getBody();
}
}
我们在前端表单提交的MultipartFile文件,在后端通过uploadImg方法,上传到GitHub,并且返回图片的地址。我们后面可以将地址存入数据库中。
package org.netease.util.imgManager;
import cn.hutool.core.codec.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class UploadGitHubImgBed {
/**
* Github私人令牌
*/
public static final String ACCESS_TOKEN = ""; //这里不展示我自己的了,需要你自己补充
/**
* github用户名
*/
public static final String OWNER = "qdfd";
/**
* 上传指定仓库
*/
public static final String REPO = "pika";
/**
* 上传时指定存放图片路径
*/
public static final String PATH = "/uploadimg/"+ "/"; //使用到了日期工具类
/**
* 用于提交描述
*/
public static final String ADD_MESSAGE = "add img";
public static final String DEL_MESSAGE = "DEL img";
//API
/**
* 新建(POST)、获取(GET)、删除(DELETE)文件:()中指的是使用对应的请求方式
* %s =>仓库所属空间地址(企业、组织或个人的地址path) (owner)
* %s => 仓库路径(repo)
* %s => 文件的路径(path)
*/
public static final String API_CREATE_POST = "https://api.github.com/repos/%s/%s/contents%s";
/**
* 生成创建(获取、删除)的指定文件路径
* @param originalFilename
* @return
*/
public static String createUploadFileUrl(String originalFilename){
//获取文件后缀
String suffix = FileUtils.getFileSuffix(originalFilename);//使用到了自己编写的FileUtils工具类
//拼接存储的图片名称
String fileName = System.currentTimeMillis()+"_"+ UUID.randomUUID().toString()+suffix;
//填充请求路径
String url = String.format(UploadGitHubImgBed.API_CREATE_POST,
UploadGitHubImgBed.OWNER,
UploadGitHubImgBed.REPO,
UploadGitHubImgBed.PATH+fileName);
return url;
}
/**
* 获取创建文件的请求体map集合:access_token、message、content
* @param multipartFile 文件字节数组
* @return 封装成map的请求体集合
*/
public static Map<String,Object> getUploadBodyMap(byte[] multipartFile){
HashMap<String, Object> bodyMap = new HashMap<>(2);
bodyMap.put("message", UploadGitHubImgBed.ADD_MESSAGE);
bodyMap.put("content", Base64.encode(multipartFile));
return bodyMap;
}
}