ファイルのアップロードおよびダウンロード機能を実装するにはどうすればよいですか?以下の記事ではgiteeをベースにしたファイルアップロード・ダウンロード機能の実装方法を紹介しますので、ご参考になれば幸いです。
ファイルのアップロードとダウンロードはプロジェクトの中核機能であり、以前のブートの統合と最適化も行います。この機能を実装するプロジェクト。
ファイルのアップロードとダウンロードには、Alibaba Cloud OSS や Huawei Cloud OSS が一般的に使用され、非常に使いやすく、公式にグラフィカル インターフェイスが提供されていますが、これらの方法は容量に応じてストレージ料金が必要であり、同様の方法です。 gitee. 公式インターフェイスを呼び出して関数を実装します。学習段階なので、gitee にウェアハウスを構築し、公式 API を使用してファイルのアップロードとウェアハウスへの削除機能を開始し、に保存されているファイル アドレスを使用することにしました。データベースを使用してファイルをブラウザ サーバー クライアントにダウンロードします。
データベース テーブルは、基本的な機能を実装するために 2 つのテーブルのみを使用します。1 つはファイル テーブル、もう 1 つはフォルダー テーブルです。
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 を開いて新しいウェアハウスを作成し、名前を入力し、初期化ウェアハウスを確認して、作成後にオープンソースとして設定します
ウェアハウスが作成されたら、[個人ホームページ] -> [個人設定] -> [プライベート トークン] を開き、呼び出し時の認証用に自分用の新しいプライベート トークンを生成します。公式インターフェースです。
# 生成時のオプションについては心配する必要はありません。独自のトークンは 1 回しか表示されないため、慎重に保存してください。
他の人が書いたものをコピーし、プライベート トークン、個人スペース、ウェアハウス名、内部のデフォルトに注意してください。ストレージ アドレスは独自のものに変更する必要があります。このツール クラスはこの情報を使用して、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> getUploadBodyMap(byte[] multipartFile){ HashMap<string> 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> getCommonBodyMap(HashMap map, String message){ HashMap<string> 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> 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> 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(); } }</string></string></string></string></string></string>
ファイル アップロードのプロセスでは、ファイル オブジェクトと関連情報をフロントエンドに渡し、次に 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; } }
コントローラーはファイルと情報を取得した後、中間ツール クラスを呼び出してファイルをアップロードし、リクエスト ヘッダーからユーザー 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)); } }</string>
このサービスは比較的シンプルで、保存時間を設定し、マッパーを呼び出して保存するだけです。
/** * 上传文件 * * @param file 用于向数据库储存的文件对象 */ @Override public void fileUpload(File file) { file.setCreateTime(new Date()); fileMapper.insert(file); }
ファイルをアップロードできます任意
gitee とデータベースに対応する結果があるかどうかを確認します
#ここでの ID は 2 です。データの一部が削除された場合、テーブルを最初から切り詰めるだけで済みます。/** * 文件下载接口 * @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); } }</string>
/** * 获取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); } }</string>
发送请求删除文件
查看数据库和gitee仓库
自此完成了文件的上传和下载功能,大家有需要的可以参考。
(学习视频分享:编程基础视频)
以上がgiteeをベースにファイルをアップロード・ダウンロードする機能を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。