您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“基于gitee如何實現上傳下載文件的功能”,內容詳細,步驟清晰,細節處理妥當,希望這篇“基于gitee如何實現上傳下載文件的功能”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
文件的上傳和下載是我們這個項目的核心功能,也是整合優化了一下以前的boot項目來實現這個功能。
對于文件的上傳和下載一般是使用阿里云OSS、華為云OSS這些,很好用而且官方提供了圖形界面,但是這些方式都需要按量儲存收費并且和gitee相似都是去調用官方接口實現功能,因為我是在學習階段,所以選擇了在gitee搭建了一個倉庫,利用官方的api向倉庫發起文件的上傳、刪除功能,并且利用數據庫儲存的文件地址實現將文件下載到瀏覽器客戶端。
數據庫的表暫時只用了兩張來實現基本功能,一個是文件表,一個是文件夾表
public class File {
@TableId(type = IdType.AUTO)
private Long id;
private String fileName;
private String filePath;
private String fileSize;
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
private Long userId;
private Long folderId;
//分享次數
private Integer shareTimes;
//文件描述
private String fileCover;
}
public class Folder {
@TableId(type = IdType.AUTO)
private Long id;
private String folderName;
private Long fatherId; //父文件夾id,為0表示沒有最上層文件夾
private Long userId;
private String folderCover;
private Boolean folderPermissions;
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
}
首先打開自己的gitee新建一個倉庫,填寫名稱,勾選初始化倉庫,創建好之后設置為開源
倉庫創建好之后打開“個人主頁”—>“個人設置”---->“私人令牌”為自己生成一個新的私人令牌用于調用官方接口時的認證。
生成時不用管選項直接生成,注意保存自己的令牌,因為只會展示一次。
這里用的別人寫好的直接copy就行,注意里面的私人令牌、個人空間、倉庫名、默認存儲地址要改成自己的,這個工具類也就是利用這些信息通過HttpUtil工具類向gitee倉庫發起上傳請求。
package com.ityz.file.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @ClassName UploadGiteeImgBedUtil
* @Author ityz
* @Date 2022/11/23 16:38
* @Description Gitee圖床工具類
*/
public class GiteeImgBedUtil {
/**
* 碼云私人令牌
*/
private static final String ACCESS_TOKEN = "0616f0e894e3c264bac45591e34a43bc"; //這里不展示我自己的了,需要你自己補充
/**
* 碼云個人空間名
*/
private static final String OWNER = "procedure-yuan-yanzu";
/**
* 上傳指定倉庫
*/
private static final String REPO = "files";
/**
* 默認上傳時指定存放圖片路徑
*/
public static final String PATH = "files/";
//API
/**
* 新建(POST)、獲取(GET)、刪除(DELETE)文件:()中指的是使用對應的請求方式
* %s =>倉庫所屬空間地址(企業、組織或個人的地址path) (owner)
* %s => 倉庫路徑(repo)
* %s => 文件的路徑(path)
*/
private static final String API_CREATE_POST = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";
/**
* 生成創建(獲取、刪除)的指定文件路徑
* @param originalFilename 原文件名
* @param path 存儲文件路徑
* @return
*/
private static String createUploadFileUrl(String originalFilename,String path){
String targetPath = path == null ? GiteeImgBedUtil.PATH : path;
//獲取文件后綴
String suffix = FileUtil.getFileSuffix(originalFilename);
//拼接存儲的圖片名稱
String fileName = System.currentTimeMillis()+"_"+ UUID.randomUUID().toString()+suffix;
//填充請求路徑
String url = String.format(GiteeImgBedUtil.API_CREATE_POST,
GiteeImgBedUtil.OWNER,
GiteeImgBedUtil.REPO,
targetPath + fileName);
return url;
}
private static String createDelFileUrl(String path){
//填充請求路徑
String url = String.format(GiteeImgBedUtil.API_CREATE_POST,
GiteeImgBedUtil.OWNER,
GiteeImgBedUtil.REPO,
path);
return url;
}
private static String createGetUrl(String path){
String targetPath = path == null ? GiteeImgBedUtil.PATH : path;
//填充請求路徑
String url = String.format(GiteeImgBedUtil.API_CREATE_POST,
GiteeImgBedUtil.OWNER,
GiteeImgBedUtil.REPO,
targetPath);
return url;
}
/**
* 獲取創建文件的請求體map集合:access_token、message、content
* @param multipartFile 文件字節數組
* @return 封裝成map的請求體集合
*/
private static Map<String,Object> getUploadBodyMap(byte[] multipartFile){
HashMap<String, Object> bodyMap = new HashMap<>(3);
bodyMap.put("access_token", GiteeImgBedUtil.ACCESS_TOKEN);
bodyMap.put("message", "add file!");
bodyMap.put("content", Base64.encode(multipartFile));
return bodyMap;
}
/**
* 創建普通攜帶請求體集合內容
* @param map 額外參數
* @param message 請求信息
* @return
*/
private static Map<String,Object> getCommonBodyMap(HashMap map, String message){
HashMap<String, Object> bodyMap = new HashMap<>(2);
bodyMap.put("access_token", GiteeImgBedUtil.ACCESS_TOKEN);
bodyMap.put("message", message);
if (map != null){
bodyMap.putAll(map);
}
return bodyMap;
}
/**
* **********封裝好的實際調用方法*******************
*/
//超時
private static int TIMEOUT = 10 * 1000;
/**
* 上傳文件
* @param filename 文件名稱
* @param path 路徑
* @param sha 必備參數from 獲取倉庫具體路徑下的內容
* @return
*/
public static String uploadFile(String path, String originalFilename, byte[] data){
String targetURL = GiteeImgBedUtil.createUploadFileUrl(originalFilename,path);
//請求體封裝
Map<String, Object> uploadBodyMap = GiteeImgBedUtil.getUploadBodyMap(data);
return HttpUtil.post(targetURL, uploadBodyMap);
}
/**
* 刪除指定path路徑下的文件
* @param filename 文件名稱
* @param path 路徑
* @param sha 必備參數from 獲取倉庫具體路徑下的內容
* @return
*/
public static String deleteFile(String path,String sha){
String delFileUrl = createDelFileUrl(path);
HashMap<String, Object> needMap = new HashMap<>(1);
needMap.put("sha",sha);//添加sha參數
return HttpUtil.createRequest(Method.DELETE, delFileUrl)
.form(getCommonBodyMap(needMap,"del file!")) //構建請求表單
.timeout(TIMEOUT)
.execute().body();
}
/**
* 獲取倉庫具體路徑下的內容,主要是獲取 sha
* @param path
* @return
*/
public static String getSha(String path){
String getShaUrl = createDelFileUrl(path);
return HttpUtil.createRequest(Method.GET, getShaUrl)
.form(getCommonBodyMap(null, "get sha!"))
.timeout(TIMEOUT)
.execute().body();
}
}
文件上傳的過程為前端傳入文件對象和相關信息然后我們向gitee發起請求將文件傳到倉庫,上傳成功之后在將返回的下載地址和相關信息存入數據庫當中。
這里我們先來編寫一個中間工具類來發起請求和拿到結果,這個代碼也寫在服務當中的話會顯得代碼太長太復雜所以我單獨拿出來寫。
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ityz.common.constants.GiteeConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* gitee文件操作api
*/
@Slf4j
public class GiteeApi {
/**
* 上傳文件api
* @param multipartFile 前端傳入的文件對象
* @param folder 文件所存文件夾名稱
* @return gitee的api上傳返回值的json對象
* @throws IOException
*/
public static JSONObject upload(MultipartFile multipartFile,String folder) throws IOException {
log.info("uploadFile()請求已來臨...");
//根據文件名生成指定的請求url
String originalFilename = multipartFile.getOriginalFilename();
if (originalFilename == null) {
log.info("服務器接收文件失敗!");
}
//Gitee請求:發送上傳文件請求
String JSONResult = GiteeImgBedUtil.uploadFile(folder, originalFilename, multipartFile.getBytes());
//解析響應JSON字符串
//上傳txt文件時會出問題,沒解決
JSONObject jsonObj = JSONUtil.parseObj(JSONResult);
//請求失敗
if (jsonObj.getObj(GiteeConstant.RESULT_BODY_COMMIT) == null) {
log.info("上傳文件失敗!");
}
//請求成功:返回下載地址
JSONObject content = JSONUtil.parseObj(jsonObj.getObj(GiteeConstant.RESULT_BODY_CONTENT));
log.info("上傳成功,下載地址為:" + content.getStr(GiteeConstant.RESULT_BODY_DOWNLOAD_URL));
return content;
}
}
controller拿到文件和信息后調用中間工具類上傳文件,然后從請求頭中拿到用戶id,從返回對象中拿到文件信息存入File類當中然后使用mybatisplus將對象存入數據庫就行。
@RestController
@Slf4j
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
@Autowired
private HttpServletRequest request;
/**
* 文件上傳接口
* @param multipartFile 上傳的文件對象
* @param fileCover 文件的描述信息
* @param folderId 文件所屬的文件夾id
* @return 用戶文件地址
* @throws IOException
*/
@PostMapping("/upload")
public Result<String> uploadFile(@RequestParam("file") MultipartFile multipartFile
, @RequestParam("fileCover") String fileCover
, @RequestParam("folderId") Long folderId) throws IOException {
JSONObject content = GiteeApi.upload(multipartFile, "test/");
//獲取userId
Long userId = Long.valueOf(TokenUtil.parseToken(request.getHeader("token")));
File file = new File();
file.setFileCover(fileCover);
file.setUserId(userId);
file.setFolderId(folderId);
file.setFileName(content.getStr(GiteeConstant.RESULT_BODY_NAME));;
file.setFileSize(content.getStr(GiteeConstant.RESULT_BODY_SIZE));
file.setFilePath(content.getStr(GiteeConstant.RESULT_BODY_DOWNLOAD_URL));
fileService.fileUpload(file);
return new Result<>(ResultCode.SUCCESS,ResultCode.UP_FILE_SUCCESS,content.getStr(GiteeConstant.RESULT_BODY_DOWNLOAD_URL));
}
}
service比較簡單,設置一個儲存時間調用mapper存入就行
/**
* 上傳文件
*
* @param file 用于向數據庫儲存的文件對象
*/
@Override
public void fileUpload(File file) {
file.setCreateTime(new Date());
fileMapper.insert(file);
}
我們隨便上傳一個文件
查看gitee和數據庫是否有相應結果
這里id為2是因為之前刪除了一條數據,想要從頭開始截斷表就行。
文件下載最初比較困擾我,有兩種方式,第一種是直接將文件對象寫入到用戶提供的本地文件夾地址,第二種是將文件下載到瀏覽器。最終選擇了第二種方式,因為用戶不用設置下載地址而且在瀏覽器下載可以看到下載過程,整個流程是利用下載地址將文件轉換為文件流寫入字節數組,在利用瀏覽器通過下載的方式寫出字節數組到輸出流。
使用文件id先從數據庫查到相應地址然后利用地址完成后續操作。
/**
* 文件下載接口
* @param fileId 文件id
* @param response http響應對象
* @return 下載結果
*/
@GetMapping("/download")
public Result<String> download(Long fileId,HttpServletResponse response) {
try {
String downloadUrl = fileService.downloadFile(fileId);
URL url = new URL(downloadUrl);
URLConnection conn = url.openConnection();
InputStream bis = conn.getInputStream();
byte[] bytes = new byte[bis.available()];
OutputStream os = response.getOutputStream();
// 從文件流讀取字節到字節數組中
while (bis.read(bytes) != -1) {
// 重置 response
response.reset();
// 設置 response 的下載響應頭
response.setContentType("application/x-download");
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(FileUtil.getFileName(downloadUrl), "UTF-8")); // 注意,這里要設置文件名的編碼,否則中文的文件名下載后不顯示
// 寫出字節數組到輸出流
os.write(bytes);
// 刷新輸出流
os.flush();
}
return new Result<>(ResultCode.SUCCESS,ResultCode.DOWN_FILE_SUCCESS);
}catch (Exception e){
e.printStackTrace();
return new Result<>(ResultCode.FAIL,ResultCode.DOWN_FILE_FAIL);
}
}
這里需要一個編寫獲取文件名的工具類,不然下載之后瀏覽器不知道文件類型
/**
* 獲取url中的文件名(取到最后一個/后面的就是文件名)
* @param url 文件地址
* @return
*/
public static String getFileName(String url) {
if(!url.equals("")){
return url.substring(url.lastIndexOf("/")+1);
}
else return "文件地址錯誤";
}
發送請求完成下載
/**
* 刪除文件api
* @param url 文件地址
*/
public static void del(String url){
if (!url.equals("") && !url.contains("master/")) {
log.info("url:" + url + " 無法解析路徑!");
}
String path = url.substring(url.indexOf("master/") + 7);
log.info("解析取得待刪除路徑:" + path);
String shaResult = GiteeImgBedUtil.getSha(path);
JSONObject jsonObj = JSONUtil.parseObj(shaResult);
String sha = jsonObj.getStr(GiteeConstant.RESULT_BODY_SHA);
//3、Gitee請求:發送刪除請求
String JSONResult = GiteeImgBedUtil.deleteFile(path, sha);
jsonObj = JSONUtil.parseObj(JSONResult);
if (jsonObj.getObj(GiteeConstant.RESULT_BODY_COMMIT) == null) {
log.info("刪除文件失敗!");
}
log.info("文件路徑為:" + path + " 刪除成功!");
}
獲取文件地址并刪除數據庫數據
/**
* 刪除文件
* @param fileId 文件id
* @return
*/
@Override
public String delFile(Long fileId) {
String url = fileMapper.selectById(fileId).getFilePath();
fileMapper.deleteById(fileId);
return url;
}
**
* 刪除文件接口
* @param fileId 前端傳入的文件id
* @return
*/
@GetMapping("/del")
public Result<String> delFile(Long fileId) {
try {
String url = fileService.delFile(fileId);
GiteeApi.del(url);
return new Result<>(ResultCode.SUCCESS,ResultCode.DEL_FILE_SUCCESS);
}
catch (Exception e){
e.printStackTrace();
return new Result<>(ResultCode.FAIL,ResultCode.DEL_FILE_FAIL);
}
}
發送請求刪除文件
查看數據庫和gitee倉庫
讀到這里,這篇“基于gitee如何實現上傳下載文件的功能”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。