基于Springboot外卖系统13:实现文件上传下载模块
1. 上傳功能模塊
1.1 上傳概述
文件上傳,也稱為upload,是指將本地圖片、視頻、音頻等文件上傳到服務器上,可以供其他用戶瀏覽或下載的過程。
文件上傳時,對頁面的form表單有如下要求:
| method | post | 必須選擇post方式提交 |
| enctype | multipart/form-data | 采用multipart格式上傳文件 |
| type | file | 使用input的file控件上傳 |
1.2 前端介紹
1). 簡單html頁面表單
<form method="post" action="/common/upload" enctype="multipart/form-data"><input name="myFile" type="file" /><input type="submit" value="提交" /> </form>2). ElementUI中提供的upload上傳組件
目前一些前端組件庫也提供了相應的上傳組件,但是底層原理還是基于form表單的文件上傳。
1.3 服務端介紹
服務端要接收客戶端頁面上傳的文件,通常都會使用Apache的兩個組件:
-
commons-fileupload
-
commons-io
而Spring框架在spring-web包中對文件上傳進行了封裝簡化代碼,只需要在Controller的方法中聲明一個MultipartFile類型的參數即可接收上傳的文件。
1.4 下載介紹
文件下載,也稱為download,是指將文件從服務器傳輸到本地計算機的過程。通過瀏覽器進行文件下載,通常有兩種表現形式:
1). 以附件形式下載,彈出保存對話框,將文件保存到指定磁盤目錄
2). 直接在瀏覽器中打開
?通過瀏覽器進行文件下載,本質上就是服務端將文件以流的形式寫回瀏覽器的過程。
1.5 上傳功能模塊邏輯分析
1.3.1 前端代碼分析
對于前端頁面文件上傳,可以使用ElementUI提供的上傳組件,將其拷貝到項目的目錄(resources/backend/page/demo)下,啟動項目,訪問上傳頁面。
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>文件上傳</title><!-- 引入樣式 --><link rel="stylesheet" href="../../plugins/element-ui/index.css" /><link rel="stylesheet" href="../../styles/common.css" /><link rel="stylesheet" href="../../styles/page.css" /> </head> <body><div class="addBrand-container" id="food-add-app"><div class="container"><el-upload class="avatar-uploader"action="/common/upload":show-file-list="false":on-success="handleAvatarSuccess":before-upload="beforeUpload"ref="upload"><img v-if="imageUrl" :src="imageUrl" class="avatar"></img><i v-else class="el-icon-plus avatar-uploader-icon"></i></el-upload></div></div><!-- 開發環境版本,包含了有幫助的命令行警告 --><script src="../../plugins/vue/vue.js"></script><!-- 引入組件庫 --><script src="../../plugins/element-ui/index.js"></script><!-- 引入axios --><script src="../../plugins/axios/axios.min.js"></script><script src="../../js/index.js"></script><script>new Vue({el: '#food-add-app',data() {return {imageUrl: ''}},methods: {handleAvatarSuccess (response, file, fileList) {this.imageUrl = `/common/download?name=${response.data}`},beforeUpload (file) {if(file){const suffix = file.name.split('.')[1]const size = file.size / 1024 / 1024 < 2if(['png','jpeg','jpg'].indexOf(suffix) < 0){this.$message.error('上傳圖片只支持 png、jpeg、jpg 格式!')this.$refs.upload.clearFiles()return false}if(!size){this.$message.error('上傳文件大小不能超過 2MB!')return false}return file}}}})</script> </body> </html>?http://localhost:8080/backend/page/demo/upload.html?
頁面效果如下:
?在上述的瀏覽器抓取的網絡請求中,上傳文件的調用url,在哪里配置的呢,這個時候,我們需要去看一下前端上傳組件。
?雖然上述是ElementUI封裝的代碼,但是實際上最終還通過file域上傳文件,如果未指定上傳文件的參數名,默認為file。
1.6 上傳服務端代碼邏輯
#?編寫文件上傳的方法, 通過MultipartFile類型的參數即可接收上傳的文件, 方法形參的名稱需要與頁面的file域的name屬性一致。
1). 獲取文件的原始文件名, 通過原始文件名獲取文件后綴
2). 通過UUID重新聲明文件名, 文件名稱重復造成文件覆蓋
3). 創建文件存放目錄
4). 將上傳的臨時文件轉存到指定位置
2 下載功能模塊
2.1 前端代碼
文件下載,前端頁面可以使用<img>標簽展示下載的圖片。
<img v-if="imageUrl" :src="imageUrl" class="avatar"></img>解析通過<img>標簽如何展示圖片數據具體的流程:
在文件上傳成功后,在 handleAvatarSuccess 方法中獲取文件上傳成功之后返回的數據(文件名),然后調用 /common/download?name=xxx 進行文件的下載。在這里,如果想讓上傳的照片能夠在頁面展示出來,所以需要在服務端將文件以流的形式寫回瀏覽器。
2.2 下載功能模塊邏輯分析
#?在 CommonController 中定義方法download,并接收頁面傳遞的參數name,然后讀取圖片文件的數據,然后以流的形式寫回瀏覽器。
1). 定義輸入流,通過輸入流讀取文件內容
2). 通過response對象,獲取到輸出流
3). 通過response對象設置響應數據格式(image/jpeg)
4). 通過輸入流讀取文件數據,然后通過上述的輸出流寫回瀏覽器
5). 關閉資源
3 上傳與下載服務端代碼實現
1). application.yml?(需要在application.yml中定義文件存儲路徑 )
server:# 端口設計port: 8080 spring:application:# 應用名稱(可選)name: reggie_take_outdatasource:# 數據集druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: 123456 mybatis-plus:configuration:#在映射實體或者屬性時,將數據庫中表名和字段名中的下劃線去掉,按照駝峰命名法映射map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:# ID生成策略:ASSIGN_ID:可以在分布式的情況下使用,生成的是Long類型的數字,可以排序性能也高,但是生成的策略和服務器時間有關,如果修改了系統時間就有可能導致出現重復主鍵id-type: ASSIGN_IDreggie: # 需要在application.yml中定義文件存儲路徑path: D:\Java-Pro\reggie_take_out\file\?2). CommonController
代碼實現:
package com.itheima.reggie.controller;import com.itheima.reggie.common.R; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile;import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.UUID;/*** Description: 文件的上傳和下載* @date 2022/8/17 9:55*/@RestController @RequestMapping("/common") @Slf4j public class CommonController {@Value("${reggie.path}")private String basePath;@PostMapping("upload")public R<String> upload(MultipartFile file){ // 這個名字必須和前端頁面的name一樣/**@Description: 文件上傳* @version v1.0* @author LiBiGo* @date 2022/8/17 10:31*/// file 是一個臨時文件 需要轉存,不然運行結束自動刪除log.info(file.toString());// 原始文件名String originalFilename = file.getOriginalFilename();// 獲得原文件后綴String suffix =originalFilename.substring(originalFilename.lastIndexOf("."));// 使用UUID重新生成文件名,防止文件名稱重復String fileName = UUID.randomUUID().toString() + suffix;// 創建目錄對象File dir = new File(basePath);// 判斷當前目錄是否存在if(!dir.exists()){// 目錄不存在,需要創建dir.mkdir();}try {file.transferTo(new File(basePath+fileName));} catch (IOException e){e.printStackTrace();}return R.success(fileName);}@GetMapping("/download")public void download(String name , HttpServletResponse response){/**@Description: 文件下載* @version v1.0* @author LiBiGo* @date 2022/8/17 10:31*/try {//輸入流,通過輸入流讀取文件內容FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));//輸出流,通過輸出流將文件寫回瀏覽器ServletOutputStream outputStream = response.getOutputStream();response.setContentType("image/jpeg"); // 設置響應的文件格式,也可以不設置int len = 0;byte[] bytes = new byte[1024];while ((len = fileInputStream.read(bytes)) != -1){outputStream.write(bytes,0,len);outputStream.flush();}//關閉資源outputStream.close();fileInputStream.close();} catch (Exception e) {e.printStackTrace();}} }總結
以上是生活随笔為你收集整理的基于Springboot外卖系统13:实现文件上传下载模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓玩机搞机-----没有第三方包 刷写
- 下一篇: 表达式的LenB(123程序设计ABC)