使用gitee作为图床 编写markdown自动上传文件
gitee
github 对于大家来说肯定不陌生了,相信大家也使用过githubpage服务搭建过自己的博客或者静态页面部署。
gitee 和github是一样的,都是代码仓库。同样的gitee也为我们提供了GitPages服务。和github不一样的是,
gitee可以创建多个Pages,我们可以用来创建自己的博客,也可以用来放置一些静态文件进行访问。下面我们就利用giteePages服务创建一个自己的远程图床服务。
为什么要做个人图床
我主要是因为以下几个原因:
服务器硬盘存储空间太小,将博客中的图片或者一些静态资源放到服务器上太占用空间了
转发其他平台的博客或者同步微信公众号的文章,图片进行了防盗链操作,无法进行正常展示
gitee免费
开始搞吧
主页地址: gitee
准备工作
注册登录码云
你需要一个账号,注册登录码云平台
码云的官网地址: gitee
创建仓库
创建一个新的仓库,这个仓库就是保存图片的仓库了
注意这里要选择 公开
创建成功之后,获取你的仓库git地址:
这个地方后续开发中会用到,一定要记得哦
https://gitee.com/quxuecx/TypechoBlogImg.git
quxuecx: 用户标识
TypechoBlogImg: 仓库名称
手动创建giteepages服务
注意:这里可以不需要进行手动创建,建议手动创建一下,主要是用来获取giteepage的访问地址
部署成功
记得你的地址,后续开发中会用到
创建私人令牌
创建一个私人秘钥 这个秘钥一定要注意保存
创建私人令牌
开始开发
码云OpenAPI :
https://gitee.com/api/v5/swagger
我们这里主要使用到了
仓库 > 新建文件:
https://gitee.com/api/v5/swagger#/postV5ReposOwnerRepoContentsPath
参数列表:点击下方的测试按钮,可以查看到请求地址
请求建立Pages --> 刷新仓库的giteePages服务
码代码
代码基本上没有什么逻辑,通过http协议请求码云的api就好了。下面是后端java代码分享
常量管理类
GiteeImgBedConstant.java
/** * 码云博客图床的常量类 * * @author: pyfysf * <p> * @qq: 337081267 * <p> * @CSDN: http://blog.csdn.net/pyfysf * <p> * @blog: http://wintp.top * <p> * @email: pyfysf@163.com * <p> * @time: 2019/12/8 */ public interface GiteeImgBedConstant { /** * TODO:这个常量是码云为您分配的私人令牌,Token 这里的代码会报错,仅仅是为了提醒您进行修改 */ String ACCESS_TOKEN = /** * 仓库所属地址 这个是您的私人用户名 具体请参考创建仓库时的注意事项 */ String OWNER = /** * TODO:仓库名称 这里是您的仓库名称 */ String REPO_NAME = /** * TODO: 上传图片的message */ String CREATE_REPOS_MESSAGE = "add img"; /** * TODO:文件前缀 */ String IMG_FILE_DEST_PATH = "/img/" + DateUtil.format(new Date(), "yyyy_MM_dd") + "/"; /** * 新建文件 * <p> * owner* 仓库所属空间地址(企业、组织或个人的地址path) * repo* 仓库路径 * path* 文件的路径 * content* 文件内容, 要用 base64 编码 * message* 提交信息 * <p> * %s =>仓库所属空间地址(企业、组织或个人的地址path) (owner) * %s => 仓库路径(repo) * %s => 文件的路径(path) */ String CREATE_REPOS_URL = "https://gitee.com/api/v5/repos/%s/%s/contents/%s"; /** * 请求建立page 如果建立了,可以刷新 * <p> * owner* 仓库所属空间地址(企业、组织或个人的地址path) * repo* 仓库 */ String BUILD_PAGE_URL = "https://gitee.com/api/v5/repos/%s/%s/pages/builds"; /** * TODO: gitpage请求路径 * 示例:"http://quxuecx.gitee.io/typechoblogimg/"; */ String GITPAGE_REQUEST_URL = }
GiteeBlogImgMController.java
import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.util.HashMap; import java.util.Map; import cn.hutool.core.codec.Base64; import cn.hutool.core.util.IdUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; import top.wintp.upuptopboot.common.constant.GiteeImgBedConstant; import top.wintp.upuptopboot.common.utils.ResultUtil; import top.wintp.upuptopboot.common.vo.Result; @Slf4j @RestController @Api(description = "码云博客图床管理接口") @RequestMapping("/api/giteeBlogImg") @Transactional public class GiteeBlogImgMController { @RequestMapping("saveImg") @ResponseBody public Result<Map<String, Object>> saveImg(@RequestParam(value = "imgFile", required = true) MultipartFile imgFile) throws Exception { Result<Map<String, Object>> result = ResultUtil.success("请求成功"); Map<String, Object> resultMap = new HashMap<String, Object>(); String trueFileName = imgFile.getOriginalFilename(); assert trueFileName != null; String suffix = trueFileName.substring(trueFileName.lastIndexOf(".")); String fileName = System.currentTimeMillis() + "_" + IdUtil.randomUUID() + suffix; String paramImgFile = Base64.encode(imgFile.getBytes()); //转存到gitee Map<String, Object> paramMap = new HashMap<>(); paramMap.put("access_token", GiteeImgBedConstant.ACCESS_TOKEN); paramMap.put("message", GiteeImgBedConstant.CREATE_REPOS_MESSAGE); paramMap.put("content", paramImgFile); String targetDir = GiteeImgBedConstant.IMG_FILE_DEST_PATH + fileName; String requestUrl = String.format(GiteeImgBedConstant.CREATE_REPOS_URL, GiteeImgBedConstant.OWNER, GiteeImgBedConstant.REPO_NAME, targetDir); System.out.println(requestUrl); String resultJson = HttpUtil.post(requestUrl, paramMap); JSONObject jsonObject = JSONUtil.parseObj(resultJson); if (jsonObject.getObj("commit") != null) { String resultImgUrl = GiteeImgBedConstant.GITPAGE_REQUEST_URL + targetDir; resultMap.put("resultImgUrl", resultImgUrl); System.out.println(resultJson); result.setCode(200); } else { result.setCode(400); } result.setResult(resultMap); return result; } @RequestMapping("refreshPage") @ResponseBody public Result<Object> refreshPage() throws Exception { Result<Object> result = ResultUtil.success("成功"); Map<String, Object> paramMap = new HashMap<>(); paramMap.put("access_token", GiteeImgBedConstant.ACCESS_TOKEN); String requestUrl = String.format(GiteeImgBedConstant.BUILD_PAGE_URL, GiteeImgBedConstant.OWNER, GiteeImgBedConstant.REPO_NAME); System.out.println(requestUrl); Map<String, Object> resultMap = new HashMap<>(); String resultJson = HttpUtil.post(requestUrl, paramMap); JSONObject jsonObject = JSONUtil.parseObj(resultJson); if (jsonObject.getStr("status") != null) { String notice = jsonObject.getStr("notice"); if (notice != null) { if ("Deployed frequently".equalsIgnoreCase(notice)) { resultMap.put("message", "部署频繁"); result.setCode(404); } else { resultMap.put("message", "其他错误"); } result.setCode(404); } } else { result.setCode(200); } System.out.println(resultJson); return result; } }
Result类:
@Data public class Result<T> implements Serializable{ private static final long serialVersionUID = 1L; /** * 成功标志 */ private boolean success; /** * 消息 */ private String message; /** * 返回代码 */ private Integer code; /** * 时间戳 */ private long timestamp = System.currentTimeMillis(); /** * 结果对象 */ private T result; }
关于代码说明:里面所用到的工具包在Hutool中,具体的import已在博文中提供。如遇到问题,欢迎加我好友哦~ QQ:337081267
后端代码就这样愉快的结束了……
前端代码分享
html版本 (基于 EditorMD)
最终结果预览
实现功能:
markdown博文编辑以及展示
粘贴剪切板图片上传至码云图床(这里注意:为了避免码云page刷新频繁,建议编辑文章结束之后再次使用刷新图床服务)
主要代码:
//监听粘贴服务 function parser() { document.getElementById('test-editormd').addEventListener('paste', function ($event) { var template = { array: ($event.clipboardData || $event.originalEvent.clipboardData).items, blob: null, url: null } for (var key in template.array) { var val = template.array[key]; if (val.kind === 'file') { template.blob = val.getAsFile(); if (template.blob) { //相应ajax等上传代码 var data = new FormData(); data.append('imgFile', template.blob); $.ajax({ type: 'POST', url: "", data: data, cache: false, processData: false, contentType: false, success: function (res) { console.log(res); if (res.code === 200) { let resultImgUrl = res.result.resultImgUrl; testEditor.insertValue("![](" + resultImgUrl + ")") layer.msg("图片上传成功了,记得最后要刷新图床哦,避免频繁刷新哦!") } else { layer.msg("图片上传失败了,请重试") } } }); } } } } ) } //刷新图床服务 $("#refreshPage").bind("click", function () { $.ajax({ type: 'POST', url: "http://api.mptask.wintp.top/api/giteeBlogImg/refreshPage", data: {}, cache: false, processData: false, contentType: false, success: function (res) { console.log(res); if (res.code === 200) { layer.msg("刷新成功") } else { let message = res.result.message layer.msg(message) } } }); });
全量代码分享:
github --> https://github.com/upuptop/EditBlogByGitee/tree/master
vue版本(基于vue-meditor)
<template> <div class="markdown"> <Markdown @on-upload-image="uploadImg" @on-paste-image="pasteImg" @on-save="save" @on-ready="ready"/> </div> </template> <script> import Markdown from 'vue-meditor'; export default { name: "markdown", components: { Markdown }, methods: { ready(param) { console.log(":ready"); console.log(param); }, save(param) { console.log(":save"); console.log(param); }, pasteImg(param) { console.log(":pasteImg"); console.log(param); //在这里可以监听到剪切板粘贴图片的事件 在这里调用后台接口即可 let fileName = param.fileName; let reqParam = new FormData() //创建form对象 reqParam.append('imgFile', param)//通过append向form对象添加数据 let config = { } this.axios.post('', reqParam, config).then(res => { console.log(res) }).catch(res => { console.log(res) }) } } } </script>
本文暂时没有评论,来添加一个吧(●'◡'●)