GitHub Rest API文档:https://docs.github.com/zh/rest/repos/contents?apiVersion=2022-11-28#create-or-update-file-contents
1. 配置 GitHub
1. 注册GitHub 账号
GitHub官网地址:https://github.com/
2. 创建仓库,点击右上角的+号,点击 New repository
3. 填写仓库信息
4. 点击右上角的头像,打开 Settings
5. 选择左侧菜单的 Developer settings
6. 点击 Personal access tokens -> Tokens (classic) -> Generate new token -> Generate new token(classic)
7. 填写 Note,勾选 repo,Expiration 指的是有效时间,根据自己的需求来选择
8. 点击生成按钮 Generate token 生成 token ,注意 token 只显示一次,记得记录保存好
2. Sping Boot 项目配置
1. application.yml
Github:
branch: xxxxxx # 上传到仓库的分支名
name: xxxxx # 提交者的用户名
email: xxxxx@qq.com # 提交者的邮箱
message: xxxxxx # 提交信息
OWNER: xxxxx # 仓库的所有者,名称不区分大小写,GitHub的账户名称
REPO: xxxxx # 仓库名称
Authorization: xxxxx # 填写上面申请的token
2. GitHubController 文件
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
@RestController
@RequestMapping("/github")
public class GithubController {
@Value("${Github.branch}")
private String branch; // Github 仓库的分支
@Value("${Github.name}")
private String committerName; // 提交者的姓名
@Value("${Github.email}")
private String committerEmail; // 提交者的邮箱
@Value("${Github.message}")
private String commitMessage; // 提交的消息
@Value("${Github.OWNER}")
private String owner; // Github 仓库的所有者
@Value("${Github.REPO}")
private String repo; // Github 仓库的名称
@Value("${Github.Authorization}")
private String token; // Github 个人访问令牌
/**
* 上传文件到Github仓库
*
* @param filePath 文件在仓库中的路径
* @param content 文件内容,要上传文件的路径
* @return ApiResponse 包含上传结果信息的响应
* @throws IOException IO异常
*/
@GetMapping("/upload")
public ApiResponse upload(@RequestParam String filePath, @RequestParam String content) throws IOException {
// 对路径进行URL编码
String path = URLEncoder.encode(filePath, "UTF-8");
System.out.println(path);
// 将内容进行Base64编码
String contents = encryptToBase64(content);
// 构建Github API的URL
String apiUrl = String.format("https://api.github.com/repos/%s/%s/contents/%s", owner, repo, path);
// 构建基本认证头部
String basicAuth = Base64.getEncoder().encodeToString((token + ":").getBytes());
String authorizationHeader = "Basic " + basicAuth;
// 构建请求体
String requestBody = String.format(
"{\"message\":\"%s\", \"branch\":\"%s\", \"committer\":{\"name\":\"%s\", \"email\":\"%s\"}, \"content\":\"%s\"}",
commitMessage, branch, committerName, committerEmail, contents
);
// 构建并发送HTTP PUT请求
URL url = new URL(apiUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setRequestProperty("Authorization", authorizationHeader);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/vnd.github.v3+json");
connection.setDoOutput(true);
// 写入请求体
connection.getOutputStream().write(requestBody.getBytes("UTF-8"));
// 读取响应
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
// 打印响应
System.out.println("Response Code: " + connection.getResponseCode());
System.out.println("Response Body: " + response.toString());
// 解析响应获取 download_url
// String downloadUrl = parseDownloadUrl(response.toString());
// 通过 cdn 加速的 download_url
String downloadUrl = "https://cdn.jsdelivr.net/gh/"+owner+"/"+repo+"/"+path;
return ApiResponse.ok(downloadUrl, "上传成功");
} finally {
connection.disconnect();
}
}
/**
* 解析Github API响应中的 download_url
*
* @param jsonResponse Github API的JSON响应
* @return download_url
*/
private static String parseDownloadUrl(String jsonResponse) {
int startIndex = jsonResponse.indexOf("\"download_url\":\"") + 16;
int endIndex = jsonResponse.indexOf("\"", startIndex);
return jsonResponse.substring(startIndex, endIndex);
}
/**
* 将内容进行Base64编码
*
* @param content 原始内容
* @return Base64编码后的内容
*/
private String encryptToBase64(String content) throws IOException {
return Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(content)));
}
}
3. 注意事项:
问题:SSL 证书验证错误
错误信息:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
解决方法:导入GitHub SSL证书
- 获取 GitHub 证书: 使用 openssl 工具获取 GitHub 的 SSL 证书
echo | openssl s_client -showcerts -connect github.com:443 2>/nul | openssl x509 > github.crt
- 导入证书到 Java TrustStore: 使用 keytool 命令将证书导入 Java 的信任存储库
keytool -import -alias github -keystore "C:\Program Files\Java\jdk<version>\jre\lib\security\cacerts" -file path\to\save\directory\github.crt
替换 <version>
为Java版本号,path\to\save\directory
为保存证书的目录
- 如果需要输入
keystore
密码,则输入changeit
- 重新运行
Java
程序,看看是否解决了 “PKIX path building failed” 错误。请注意,这是一种快速的解决方案,但在生产环境中,请使用受信任的证书颁发机构(CA)签署的 SSL 证书以确保通信的安全性。