Vue+Springboot使用Gitee图床上传图片,另附删除图片功能
前端代码:
前端使用vue+elementui上传组件操作
直接上代码:
<!-- 设备管理 -->
<template>
<div class=''>
<el-upload :action="reqUrl" list-type="picture-card" :http-request="uploadSectionFile"
:on-remove="handleRemove" >
<i class="el-icon-plus"></i>
</el-upload>
</div>
</template>
<script>
export default {
//import引入的组件需要注入到对象中才能使用
components: {
},
data() {
//这里存放数据
return {
reqUrl: "/uploadImg",
imgUrl:""
};
},
//方法集合
methods: {
//移除之后删除图片
handleRemove(file, fileList) {
//访问后端删除图片
this.$axios.delete("/delImg",{
params:{
imgPath:this.imgUrl,
}
})
.then((result) => {
if(!result.success){
this.$message.error(result.message);
}
})
},
//以下是重点,覆盖默认上传方法
uploadSectionFile(params) {
// console.log(params)
let formData = new FormData();
formData.append(params.filename, params.file);
this.$axios.post(params.action, formData, {
headers: {
'Content-Type': 'multipart/form-data' } })
.then((result) => {
this.imgUrl = result.data;
})
},
},
created() {
},
mounted() {
},
}
</script>
<style scoped>
</style>
重点代码是uploadSectionFile方法,el-upload默认action是有跨域拦截的,使用自定义请求方式就没有这样的问题了。请求方法中的代码是重点,需要重新定义formData
Gitee操作:
首先创建Gitee仓库:操作步骤如下:
接下来创建私人令牌,授予所有权限,否则无法访问。具体操作如下:
点击头像选择设置-》安全设置,选项有私人令牌:
生成私人令牌时需要输入描述表示这是干什么的私人令牌。另外需要登录密码验证。成功之后如下显示:
可以将私人另外复制另存在文本文档中,关闭页面将再也看不到私人令牌码
开发使用
这里使用Gitee的OpenApi操作,方便写入代码,例如新建文件的格式如下:
这里说明一点,owner是个人空间地址,如果不清楚,可以照如下图操作查看:
repo就是刚才创建仓库的名字,path是文件路径,可带文件夹,可以不创建,会自动创建。之后就可以写Java代码了
后端代码:
- 首先定义GiteeImgBed类,设置相关属性
package bjwl.jk.zg.limsser.util;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 配置码云图床
*/
public class GiteeImgBed {
public static String getNowDate() {
Date now = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
return formatter.format(now);
}
//码云私人令牌,需要补充
public static final String ACCESS_TOKEN = "";
//个人空间名,需要补充
public static final String OWNER = "";
//仓库名,需要补充
public static final String REPO_NAME = "";
//文件夹路径
public static final String PATH = "/img/" + getNowDate() + "/";
//message消息
public static final String ADD_MESSAGE = "add img";
public static final String DEl_MESSAGE = "del img";
/**
* 新建文件请求路径
* <p>
* owner* 仓库所属空间地址(企业、组织或个人的地址path)
* repo* 仓库路径
* path* 文件的路径
* content* 文件内容, 要用 base64 编码
* message* 提交信息
* <p>
* %s =>仓库所属空间地址(企业、组织或个人的地址path) (owner)
* %s => 仓库路径(repo)
* %s => 文件的路径(path)
*/
public static String CREATE_REPOS_URL = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";
/**
* 获取路径下所有的内容
* <p>
* owner* 仓库所属空间地址(企业、组织或个人的地址path)
* repo* 仓库路径
* path* 文件的路径
* content* 文件内容, 要用 base64 编码
* message* 提交信息
* <p>
* %s =>仓库所属空间地址(企业、组织或个人的地址path) (owner)
* %s => 仓库路径(repo)
* %s => 文件的路径(path)
*/
public static String GET_IMG_URL = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";
/**
* 删除文件请求路径
* <p>
* owner* 仓库所属空间地址(企业、组织或个人的地址path)
* repo* 仓库路径
* path* 文件的路径
* content* 文件内容, 要用 base64 编码
* message* 提交信息
* <p>
* %s =>仓库所属空间地址(企业、组织或个人的地址path) (owner)
* %s => 仓库路径(repo)
* %s => 文件的路径(path)
*/
public static String DEL_IMG_URL = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";
}
- 导入hutool工具包,发送请求以及JSON处理,可以去MavenRepository查看最新版
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.8</version>
</dependency>
- 写上传图片控制器
package bjwl.jk.zg.limsser.controller;
import bjwl.jk.zg.limsser.util.GiteeImgBed;
import bjwl.jk.zg.limsser.util.Result;
import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 上传图床
*/
@RestController
@Transactional(rollbackFor = Exception.class)
public class UploadController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 上传图片
* @param file
* @return
* @throws Exception
*/
@PostMapping("/uploadImg")
@ResponseBody
public Result uploadImg(@RequestParam("file") MultipartFile file) throws Exception {
logger.info("请求成功");
String originaFileName = file.getOriginalFilename();
//上传图片不存在时
if(originaFileName == null){
return Result.fail(Result.IMG_EXIST_ERROR,Result.IMG_EXIST_ERROR_MSG);
}
String suffix = originaFileName.substring(originaFileName.lastIndexOf("."));
//设置图片名字
String fileName = System.currentTimeMillis() + "_" + UUID.randomUUID().toString() + suffix;
String paramImgFile = Base64.encode(file.getBytes());
//设置转存到Gitee仓库参数
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("access_token", GiteeImgBed.ACCESS_TOKEN);
paramMap.put("message", GiteeImgBed.ADD_MESSAGE);
paramMap.put("content", paramImgFile);
//转存文件路径
String targetDir = GiteeImgBed.PATH + fileName;
//设置请求路径
String requestUrl = String.format(GiteeImgBed.CREATE_REPOS_URL, GiteeImgBed.OWNER,
GiteeImgBed.REPO_NAME, targetDir);
logger.info("请求Gitee仓库路径:{}",requestUrl);
String resultJson = HttpUtil.post(requestUrl, paramMap);
JSONObject jsonObject = JSONUtil.parseObj(resultJson);
//表示操作失败
if (jsonObject==null || jsonObject.getObj("commit") == null) {
return Result.fail(Result.SERVE_ERROR,Result.SERVE_ERROR_MSG);
}
JSONObject content = JSONUtil.parseObj(jsonObject.getObj("content"));
return Result.success("",content.getObj("download_url"));
}
/**
* 删除图片
* @param imgPath
* @return
* @throws Exception
*/
@DeleteMapping("/delImg")
@ResponseBody
public Result delImg(@RequestParam(value = "imgPath") String imgPath) throws Exception {
//路径不存在不存在时
if(imgPath == null || imgPath.trim().equals("")){
return Result.fail(Result.SERVE_ERROR,"删除失败");
}
String path = imgPath.split("master/")[1];
//上传图片不存在时
if(path == null || path.trim().equals("")){
return Result.fail(Result.IMG_EXIST_ERROR,Result.IMG_EXIST_ERROR_MSG);
}
//设置请求路径
String requestUrl = String.format(GiteeImgBed.GET_IMG_URL, GiteeImgBed.OWNER,
GiteeImgBed.REPO_NAME, path);
logger.info("请求Gitee仓库路径:{}",requestUrl);
//获取图片所有信息
String resultJson = HttpUtil.get(requestUrl);
JSONObject jsonObject = JSONUtil.parseObj(resultJson);
if (jsonObject == null) {
logger.error("Gitee服务器未响应,message:{}",jsonObject);
return Result.fail(Result.SERVE_ERROR,Result.SERVE_ERROR_MSG);
}
//获取sha,用于删除图片
String sha = jsonObject.getStr("sha");
//设置删除请求参数
Map<String,Object> paramMap = new HashMap<>();
paramMap.put("access_token", GiteeImgBed.ACCESS_TOKEN);
paramMap.put("sha", sha);
paramMap.put("message", GiteeImgBed.DEl_MESSAGE);
//设置删除路径
requestUrl = String.format(GiteeImgBed.DEL_IMG_URL, GiteeImgBed.OWNER,
GiteeImgBed.REPO_NAME, path);
logger.info("请求Gitee仓库路径:{}",requestUrl);
//删除文件请求路径
resultJson = HttpRequest.delete(requestUrl).form(paramMap).execute().body();
HttpRequest.put(requestUrl).form(paramMap).execute().body();
jsonObject = JSONUtil.parseObj(resultJson);
//请求之后的操作
if(jsonObject.getObj("commit") == null){
logger.error("Gitee服务器未响应,message:{}",jsonObject);
return Result.fail(Result.SERVE_ERROR,Result.SERVE_ERROR_MSG);
}
return Result.success("删除成功");
}
}
- 以上控制器返回值可自定义操作,返回数据样式可以使用OpenApi做测试样例,根据response数据格式返回自己需要的参数。另外
上面使用Result是自定义结果封装类型,可自定义。有需要,可以参考
下面代码:
package bjwl.jk.zg.limsser.util;
import com.github.pagehelper.PageInfo;
import java.util.HashMap;
import java.util.Map;
/**
* 返回前端页面结果,包含是否登录成功,访问的信息,数据
*/
public class Result {
/**
* 成功
*/
public static final int SUCCESS = 200;
/**
* 服务器逻辑错误
*/
public static final int SERVE_ERROR = 500;
public static final String SERVE_ERROR_MSG = "服务器内部异常";
/**
* 重复登录
*/
public static final int REPEAT_LOGIN = 506;
public static final String REPEAT_LOGIN_MSG = "您已在其他位置登录。是否重新登录?";
/**
* 用户名密码错误
*/
public static final int LOGIN_ERROR = 507;
public static final String LOGIN_ERROR_MSG = "用户名或密码错误";
/**
* 操作数据库错误
*/
public static final int OPERATION_DB_ERROR = 508;
public static final String OPERATION_DB_ERROR_MSG = "操作异常";
/**
* 图片不存在
*/
public static final int IMG_EXIST_ERROR = 509;
public static final String IMG_EXIST_ERROR_MSG = "上传图片不存在";
/**
* 是否访问成功
*/
private boolean success;
/**
* 成功与否的信息
*/
private String message;
/**
* 状态码
*/
private int code;
/**
* 携带数据
*/
private Object data;
/**
* 判断是否已登录
*/
private boolean login;
/**
* 未登录的构造方法
*/
public Result() {
this.login = false;
}
private Result(boolean success,int code, String message, Object data) {
this.success = success;
this.message = message;
this.code = code;
this.data = data;
this.login = true;
}
public boolean isSuccess() {
return success;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public Object getData() {
return data;
}
public boolean isLogin() {
return login;
}
public static Result success(){
return new Result(true,SUCCESS,null,null);
}
public static Result success(String message){
return new Result(true,SUCCESS,message,null);
}
public static Result success(String message, Object data){
return new Result(true,SUCCESS,message,data);
}
public static Result fail(int code){
return new Result(false,code,null,null);
}
public static Result fail(int code,String message){
return new Result(false,code,message,null);
}
public static Result fail(int code,String message, Object data){
return new Result(false,code,message,data);
}
}