NiceLeeのBlog 用爱发电 bilibili~

薅个图床 - 基于GitHub API的文件创建与更新

2019-08-27
nIceLee

阅读:


听说新浪有了防盗链,羊毛党想再薅个免费的图床。
图床有两个要求,能够方便的上传图片,同时对应的图片链接能显示在不同网站。
Github就不错,上传文件肯定没问题;同时因为本身就提供自定义域名的Pages服务,想必不会对Referer标签有限制。
要是访问速度再快点简直完美。

前言

  • 其实git本身上传文件一点毛病木有,但要实现程序化、自动化、批量化,最好可以直接通过HTTP进行。
  • 查了一下Github API,有以下接口:

    这里必需的是指定路径、message(可写死,如”.”)、content(经过Base64编码的文件内容)、sha(更新已存在文件时需要),以及授权用token
    • 关于sha
      • 图床一般是新建,大概率无需用到
      • 如果实在需要,那么可以先请求得到sha,详见这里
    • 关于token
      • settings里面设置。
      • 参考官方指导,在请求头部设置好即可。
        “Authorization: token OAUTH-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;
}

源代码

FileUploader4Github


内容
隐藏