TimeMagician 2020-03-04
推荐看 这里, 已经总结了 免费图床点这里
提供一个思路, 使用onedriver 或 google driver api 自建免费图床
注意 scope 权限 , redirect_uri 授权成功跳转地址, 获取code, 所有的 auth2 都是这个流程
public String getAuthUrl(Map<String, String> params0){ String url = Constants.get("login_url") +"/authorize"; url += "?client_id=" + Constants.get("client_id"); url += "&response_type=code"; url += "&redirect_uri=" + Constants.get("redirect_uri"); url += "&scope=offline_access%20Files.ReadWrite.All%20Sites.Read.All%20User.Read"; return url; }
code是上面获取到的, 注意 redirect_uri 相同 , client_secret 密钥, 在建立clientid的地方
获取到 access_token- 用于api请求的token, expires_in - token过期时间缓存一下, refresh_token-刷新token 用的
public String getToken(Map<String, String> params0){ String code = params0.get("code"); String url = Constants.get("login_url") +"/token"; HashMap<String, String> params = new HashMap<>(); params.put("client_id", Constants.get("client_id")); params.put("redirect_uri", Constants.get("redirect_uri")); params.put("client_secret", Constants.get("client_secret")); params.put("code", code); params.put("grant_type", "authorization_code"); Map<String, Object> resp = OKHttpUtil.post(url, params);; LogUtil.info("getToken->" + resp); String token = (String) resp.get("access_token"); int expires_in = (int) resp.get("expires_in") ; VcodeUtil.timedCache.put("access_token", token, expires_in* 1000); String refresh_token = (String) resp.get("refresh_token"); VcodeUtil.timedCache.put("refresh_token", refresh_token, expires_in* 1000 * 36); return token; }
缓存 access_token 3600秒, 失效后使用 refresh_token 刷新 access_token , refresh_token的 时效较长, 微软没有指定具体多久,
测试 至少在 天级别以上
public String getTokenByCache(Map<String, String> params0){ String token = (String) VcodeUtil.timedCache.getNotUpLastAccess("access_token"); if (token != null) { return token; } String refresh_token = (String) VcodeUtil.timedCache.getNotUpLastAccess("refresh_token"); String url = Constants.get("login_url") +"/token"; HashMap<String, String> params = new HashMap<>(); params.put("client_id", Constants.get("client_id")); params.put("scope", "offline_access Files.ReadWrite.All Sites.Read.All User.Read"); params.put("refresh_token", refresh_token); params.put("redirect_uri", Constants.get("redirect_uri")); params.put("client_secret", Constants.get("client_secret")); params.put("grant_type", "refresh_token"); Map<String, Object> resp = OKHttpUtil.post(url, params);; LogUtil.info("getToken->" + resp); token = (String) resp.get("access_token"); int expires_in = (int) resp.get("expires_in") ; VcodeUtil.timedCache.put("access_token", token, expires_in* 1000); refresh_token = (String) resp.get("refresh_token"); VcodeUtil.timedCache.put("refresh_token", refresh_token, expires_in* 1000 * 36); return token; }
//PUT /me/drive/items/{parent-id}:/{filename}:/content , 上传地址很费解, 这里我做了例子
这样好理解一点, 使用 绝对路径上传, body 直接是文件流
/SEARCH_APP/upload/201912/10/Q5pe5A.jpg 这里是文件路劲
https://graph.microsoft.com/v1.0/me/drive/root:/SEARCH_APP/upload/201912/10/Q5pe5A.jpg:/content
上传成功后 会返回 这个 item 的信息, 里面有下载地址, 保存这个 id, 和 路径, 下载的时候提供 itemid 下载方式 和路径方式
public String upload(String uploadPath, String suffix, ByteArrayOutputStream out) throws Exception{ byte[] bytes = out.toByteArray(); long id = MD5.md5_long(bytes); Map<String, Object> ins = getIns(id); if(!ins.isEmpty()) { return (String) ins.get("itemid"); } String date = BaseUtil.getFormatDate().replaceFirst("/", ""); uploadPath += date; String filename = uploadPath + "/" + RandomStringUtils.randomAlphanumeric(6) +"." + suffix; //PUT /me/drive/items/{parent-id}:/{filename}:/content String url = "https://graph.microsoft.com/v1.0/me/drive/root:" + filename +":/content"; HttpRequest request = new HttpRequest(url, Method.put); request.setContentType("image/jpeg"); request.addHeader("Authorization", "Bearer " + getTokenByCache(null)); request.setRequestBody(bytes); HttpResponse res = OKHttpUtil.request(request); // 返回的 id 就是 itemid, 可以用此id做一些操作 保存itemid 和 filePath String resStr= res.getResponseString(); Map<String, Object> resMap = (Map<String, Object>) OKHttpUtil.deserialize(resStr); String itemid = (String) resMap.get("id"); return itemid; }
String url = "https://graph.microsoft.com/v1.0/me/drive/items/"+itemid+"/content"; // 下載 按itemid
String url = "https://graph.microsoft.com/v1.0/me/drive/root:" + filepath +":/content"; // 按文件路劲
看代码, 上面 带了注释, 下载地址, 预览地址, 和分享地址, 具体实现 看 oneApi, 我都测试过
成功请求后会出现 302 跳转, 一般 httpclient 都会自己跳, 不想跳的找配置 获取Location 可以查看地址
public Object downLoad(Map<String, String> params) throws Exception{ String itemid = params.get("id"); // String url = "https://graph.microsoft.com/v1.0/me/drive/root:" + filepath +":/content"; // 按文件路劲 // String url = "https://graph.microsoft.com/v1.0/me/drive/items/01RHKEMNKSNBGOHRSDPBHJI43LRLM62MV7/preview"; // 預覽按itemid // String url = "https://graph.microsoft.com/v1.0/me/drive/items/01RHKEMNKSNBGOHRSDPBHJI43LRLM62MV7/createLink"; // 分享按itemid String url = "https://graph.microsoft.com/v1.0/me/drive/items/"+itemid+"/content"; // 下載 按itemid HttpRequest request = new HttpRequest(url, Method.get); request.addHeader("Authorization", "Bearer " + getTokenByCache(null)); //request.setContentType("application/json"); //request.setRequestBody("{\"chromeless\":\"true\"}".getBytes()); HttpResponse resp = OKHttpUtil.request(request); // System.out.println(resp.getResponseString()); // System.out.println(resp.getHeader("Location")); // 302 跳转, 自动重新获取图片 URL return resp.getRespInputsStream(); }
推廣 影視在線搜索, 有倫理 有美劇, 有動漫 cocook 全網影視搜索
推廣 每日熱點 cncknews
一款定位于Markdown文章排版与一键发布本地文章到等平台的Markdown编辑器。你可以尝试用JustWrite写作,因为JustWrite可以帮你排版,帮你美化,帮你处理本地图片,帮你一键发布!