怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

怎么實(shí)現(xiàn)文件的上傳下載功能?下面本篇文章給大家介紹一下基于gitee實(shí)現(xiàn)文件上傳和下載功能的方法,希望對大家有所幫助!

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

方案的選擇

? 文件的上傳和下載是我們這個(gè)項(xiàng)目的核心功能,也是整合優(yōu)化了一下以前的boot項(xiàng)目來實(shí)現(xiàn)這個(gè)功能。

? 對于文件的上傳和下載一般是使用阿里云OSS、華為云OSS這些,很好用而且官方提供了圖形界面,但是這些方式都需要按量儲存收費(fèi)并且和gitee相似都是去調(diào)用官方接口實(shí)現(xiàn)功能,因?yàn)槲沂窃趯W(xué)習(xí)階段,所以選擇了在gitee搭建了一個(gè)倉庫,利用官方的api向倉庫發(fā)起文件的上傳、刪除功能,并且利用數(shù)據(jù)庫儲存的文件地址實(shí)現(xiàn)將文件下載到瀏覽器客戶端。

數(shù)據(jù)庫表的設(shè)計(jì)

? 數(shù)據(jù)庫的表暫時(shí)只用了兩張來實(shí)現(xiàn)基本功能,一個(gè)是文件表,一個(gè)是文件夾表

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;     //分享次數(shù)     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倉庫

? 首先打開自己的gitee新建一個(gè)倉庫,填寫名稱,勾選初始化倉庫,創(chuàng)建好之后設(shè)置為開源

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

? 倉庫創(chuàng)建好之后打開“個(gè)人主頁”—>“個(gè)人設(shè)置”—->“私人令牌”為自己生成一個(gè)新的私人令牌用于調(diào)用官方接口時(shí)的認(rèn)證。

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

? 生成時(shí)不用管選項(xiàng)直接生成,注意保存自己的令牌,因?yàn)橹粫?huì)展示一次。

gitee圖床工具類的編寫

? 這里用的別人寫好的直接copy就行,注意里面的私人令牌、個(gè)人空間、倉庫名、默認(rèn)存儲地址要改成自己的,這個(gè)工具類也就是利用這些信息通過HttpUtil工具類向gitee倉庫發(fā)起上傳請求。

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";  //這里不展示我自己的了,需要你自己補(bǔ)充       /**      * 碼云個(gè)人空間名      */     private static final String OWNER = "procedure-yuan-yanzu";       /**      * 上傳指定倉庫      */     private static final String REPO = "files";       /**      * 默認(rèn)上傳時(shí)指定存放圖片路徑      */     public static final String PATH = "files/";      //API     /**      * 新建(POST)、獲取(GET)、刪除(DELETE)文件:()中指的是使用對應(yīng)的請求方式      * %s =>倉庫所屬空間地址(企業(yè)、組織或個(gè)人的地址path)  (owner)      * %s => 倉庫路徑(repo)      * %s => 文件的路徑(path)      */     private static final String API_CREATE_POST = "https://gitee.com/api/v5/repos/%s/%s/contents/%s";       /**      * 生成創(chuàng)建(獲取、刪除)的指定文件路徑      * @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;     }      /**      * 獲取創(chuàng)建文件的請求體map集合:access_token、message、content      * @param multipartFile 文件字節(jié)數(shù)組      * @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;     }      /**      * 創(chuàng)建普通攜帶請求體集合內(nèi)容      * @param map 額外參數(shù)      * @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;     }      /**      * **********封裝好的實(shí)際調(diào)用方法*******************      */      //超時(shí)     private static int TIMEOUT = 10 * 1000;      /**      * 上傳文件      * @param filename 文件名稱      * @param path 路徑      * @param sha 必備參數(shù)from 獲取倉庫具體路徑下的內(nèi)容      * @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 必備參數(shù)from 獲取倉庫具體路徑下的內(nèi)容      * @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參數(shù)         return HttpUtil.createRequest(Method.DELETE, delFileUrl)                 .form(getCommonBodyMap(needMap,"del file!"))  //構(gòu)建請求表單                 .timeout(TIMEOUT)                 .execute().body();     }      /**      * 獲取倉庫具體路徑下的內(nèi)容,主要是獲取 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();     }  }

文件上傳接口?

? 文件上傳的過程為前端傳入文件對象和相關(guān)信息然后我們向gitee發(fā)起請求將文件傳到倉庫,上傳成功之后在將返回的下載地址和相關(guān)信息存入數(shù)據(jù)庫當(dāng)中。

中間工具類

? 這里我們先來編寫一個(gè)中間工具類來發(fā)起請求和拿到結(jié)果,這個(gè)代碼也寫在服務(wù)當(dāng)中的話會(huì)顯得代碼太長太復(fù)雜所以我單獨(dú)拿出來寫。

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()請求已來臨...");         //根據(jù)文件名生成指定的請求url         String originalFilename = multipartFile.getOriginalFilename();         if (originalFilename == null) {             log.info("服務(wù)器接收文件失??!");         }         //Gitee請求:發(fā)送上傳文件請求         String JSONResult = GiteeImgBedUtil.uploadFile(folder, originalFilename, multipartFile.getBytes());         //解析響應(yīng)JSON字符串         //上傳txt文件時(shí)會(huì)出問題,沒解決         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

? controller拿到文件和信息后調(diào)用中間工具類上傳文件,然后從請求頭中拿到用戶id,從返回對象中拿到文件信息存入File類當(dāng)中然后使用mybatisplus將對象存入數(shù)據(jù)庫就行。

@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比較簡單,設(shè)置一個(gè)儲存時(shí)間調(diào)用mapper存入就行

/**      * 上傳文件      *      * @param file 用于向數(shù)據(jù)庫儲存的文件對象      */     @Override     public void fileUpload(File file) {         file.setCreateTime(new Date());         fileMapper.insert(file);     }

接口測試

? 我們隨便上傳一個(gè)文件

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

? ?查看gitee和數(shù)據(jù)庫是否有相應(yīng)結(jié)果

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

?怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

? ?這里id為2是因?yàn)橹皠h除了一條數(shù)據(jù),想要從頭開始截?cái)啾砭托小?/p>

文件下載接口

? 文件下載最初比較困擾我,有兩種方式,第一種是直接將文件對象寫入到用戶提供的本地文件夾地址,第二種是將文件下載到瀏覽器。最終選擇了第二種方式,因?yàn)橛脩舨挥迷O(shè)置下載地址而且在瀏覽器下載可以看到下載過程,整個(gè)流程是利用下載地址將文件轉(zhuǎn)換為文件流寫入字節(jié)數(shù)組,在利用瀏覽器通過下載的方式寫出字節(jié)數(shù)組到輸出流。

controller

? 使用文件id先從數(shù)據(jù)庫查到相應(yīng)地址然后利用地址完成后續(xù)操作。

/**      * 文件下載接口      * @param fileId 文件id      * @param response http響應(yīng)對象      * @return 下載結(jié)果      */     @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();             // 從文件流讀取字節(jié)到字節(jié)數(shù)組中             while (bis.read(bytes) != -1) {                 // 重置 response                 response.reset();                 // 設(shè)置 response 的下載響應(yīng)頭                 response.setContentType("application/x-download");                 response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(FileUtil.getFileName(downloadUrl), "UTF-8"));  // 注意,這里要設(shè)置文件名的編碼,否則中文的文件名下載后不顯示                 // 寫出字節(jié)數(shù)組到輸出流                 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);         }     }

? 這里需要一個(gè)編寫獲取文件名的工具類,不然下載之后瀏覽器不知道文件類型

/**      * 獲取url中的文件名(取到最后一個(gè)/后面的就是文件名)      * @param url 文件地址      * @return      */     public static String getFileName(String url) {         if(!url.equals("")){         return url.substring(url.lastIndexOf("/")+1);         }         else return "文件地址錯(cuò)誤";     }

接口測試?

? 發(fā)送請求完成下載

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

文件刪除接口

中間工具類

/**      * 刪除文件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請求:發(fā)送刪除請求         String JSONResult = GiteeImgBedUtil.deleteFile(path, sha);         jsonObj = JSONUtil.parseObj(JSONResult);         if (jsonObj.getObj(GiteeConstant.RESULT_BODY_COMMIT) == null) {             log.info("刪除文件失?。?quot;);         }         log.info("文件路徑為:" + path + " 刪除成功!");     }

service

? 獲取文件地址并刪除數(shù)據(jù)庫數(shù)據(jù)

/**      * 刪除文件      * @param fileId 文件id      * @return      */     @Override     public String delFile(Long fileId) {         String url = fileMapper.selectById(fileId).getFilePath();         fileMapper.deleteById(fileId);         return url;     }

controller

**      * 刪除文件接口      * @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);         }     }

接口測試

發(fā)送請求刪除文件

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

?查看數(shù)據(jù)庫和gitee倉庫

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

怎么基于gitee實(shí)現(xiàn)上傳下載文件的功能

? ?自此完成了文件的上傳和下載功能,大家有需要的可以參考。

(學(xué)習(xí)視頻分享:編程基礎(chǔ)視頻

以上就是怎么基于

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊14 分享