听说新浪有了防盗链,羊毛党想再薅个免费的图床。
图床有两个要求,能够方便的上传图片,同时对应的图片链接能显示在不同网站。
Github就不错,上传文件肯定没问题;同时因为本身就提供自定义域名的Pages服务,想必不会对Referer标签有限制。
要是访问速度再快点简直完美。
前言
- 其实git本身上传文件一点毛病木有,但要实现程序化、自动化、批量化,最好可以直接通过HTTP进行。
- 查了一下Github API,有以下接口:
这里必需的是指定路径、message(可写死,如”.”)、content(经过Base64编码的文件内容)、sha(更新已存在文件时需要),以及授权用token
参考实现
/**
* 更新文件(先get访问得到sha,然后再put)
*
* @param url https://api.github.com/repos/:owner/:repo/contents/:path
* @param file 需确保文件存在
* @param token 用于鉴权
* @return
*/
public static boolean update(String url, File file, String token) {
long begin = System.currentTimeMillis();
System.out.println("获取文件SHA...");
String sha = getSHA(url);
if(sha == null)
return false;
long end = System.currentTimeMillis();
System.out.printf("获取文件SHA 耗时 %ds\n", (end - begin) / 1000);
System.out.println("上传开始...");
//StringBuffer result = new StringBuffer();
BufferedReader in = null;
HttpURLConnection conn = null;
try {
URL realUrl = new URL(url);
conn = (HttpURLConnection) realUrl.openConnection();
conn.setConnectTimeout(120000);
conn.setReadTimeout(120000);
// 设置
conn.setDoOutput(true); // 需要输出
conn.setDoInput(true); // 需要输入
conn.setUseCaches(false); // 不允许缓存
conn.setRequestMethod("PUT"); // 设置PUT方式连接
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "token " + token);
conn.setRequestProperty("User-Agent", "Github File Uploader App");
conn.connect();
// 传输数据
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
// 传输json头部
dos.writeBytes("{\"message\":\".\",\"sha\":\"" + sha +"\",\"content\":\"");
// 传输文件内容
byte[] buffer = new byte[1024 * 1002]; // 3的倍数
RandomAccessFile raf = new RandomAccessFile(file, "r");
long size = raf.read(buffer);
while (size > -1) {
if (size == buffer.length) {
dos.write(Base64.getEncoder().encode(buffer));
} else {
byte tmp[] = new byte[(int) size];
System.arraycopy(buffer, 0, tmp, 0, (int) size);
dos.write(Base64.getEncoder().encode(tmp));
}
size = raf.read(buffer);
}
raf.close();
// 传输json尾部
dos.writeBytes("\"}");
dos.flush();
dos.close();
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
//result.append(line).append("\n");
}
} catch (Exception e) {
System.out.println("发送PUT请求出现异常!");
e.printStackTrace();
return false;
} finally {
try {
in.close();
} catch (Exception e2) {
}
}
end = System.currentTimeMillis();
System.out.printf("上传结束,耗时 %ds\n", (end - begin) / 1000);
//result.toString()
return true;
}
/**
* 获取url 对应的SHA
* @param url
* @param token
* @return
*/
static Pattern pattern = Pattern.compile("\"sha\": *\"([^\"]+)\"");
public static String getSHA(String url) {
StringBuffer result = new StringBuffer();
BufferedReader in = null;
HttpURLConnection conn = null;
try {
URL realUrl = new URL(url);
conn = (HttpURLConnection) realUrl.openConnection();
conn.setConnectTimeout(120000);
conn.setReadTimeout(120000);
conn.setRequestMethod("GET");
conn.setRequestProperty("User-Agent", "Github File Uploader App");
conn.connect();
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result.append(line).append("\n");
}
Matcher matcher = pattern.matcher(result.toString());
if(matcher.find()) {
return matcher.group(1);
}
} catch (Exception e) {
System.out.println("请求SHA出现异常!");
e.printStackTrace();
} finally {
try {
in.close();
} catch (Exception e2) {
}
}
return null;
}