1、大緻思路
以下是基于先處理圖檔、後端傳回圖檔位址進行的
==存資料==
1、将圖檔資訊送出到後端
2、後端處理
3、後端傳回前端圖檔的通路位址
4、前端将圖檔位址存入要送出的表單中
5、将整個表單送出到後端、将資料存入資料庫
==取資料==
1、前端擷取後端傳回的資訊(包含圖檔的通路路徑)
2、将通路圖檔的資源放到對應的标簽或者元件中、按照自己的方式進行展示。(如果後端沒有做圖檔資源的位址映射、會顯示找不到對應的資源)
<hr>
2、将圖檔和表單資料儲存的資料庫
2.1 前端檔案上傳部分
隻給出檔案上傳部分、其餘的就是正常的表單
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iN2MzN5IjNwYzN2YTZkFjNzYzXwETNwETMyAzLcFTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
<el-form-item label="上傳檔案">
<input
@change="upload"
@click="clearFile"
multiple="multiple"
type="file"
ref="file"
/>
</el-form-item>
這裡可以選擇使用上傳多個檔案、是以使用集合的形式。<為了後期擴充多檔案上傳、暫時保留、也可以選擇 不适用集合形式。隻上傳一個檔案>。這裡使用==FormData==來傳輸、然後要在請求頭中加上
'Content-Type': 'multipart/form-data'
我這裡對axios進行了二次封裝、請求方式有所不同。你們按照自己的方式正常發送接口請求就可以。
//檔案上傳
upload: function () {
let files = this.$refs.file.files;
const _this = this;
for (let i = 0; i < files.length; i++) {
let formData = new FormData();
formData.append("file", files[i]);
this.$axios.uploadFile(formData).then((res) => {
if (res.code == 200) {
_this.$message("檔案上傳成功");
console.log(res.data.fileName);
this.GoodsInfoForm.fileName = res.data.fileName;
console.log(this.GoodsInfoForm.fileName);
} else {
_this.$message("error", res.data.msg);
}
});
}
},
==友情提示:以下兩個點可以忽略不看,對axios二次封裝的一些小記錄==
我這裡進行了axios的二次封裝、是以調用接口的方式有所不同。你們按照自己的配置正常發送接口請求就行
/**
* 檔案上傳
*/
uploadFile: (params) => {
return Post('http://localhost:8282/goodsInfo/upload', params);
}
這個也是進行的axios的二次封裝、可以忽略。重要的一點是請求頭中加上
'Content-Type': 'multipart/form-data'
const instance = axios.create({
baseURL: 'http://localhost:8282',
timeout: 3000,
headers: {
post: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' ,
'Content-Type': 'multipart/form-data'
}
}
})
2.2 後端處理檔案的接口部分
2.2.1使用工具類操作
在pom檔案中引入操作File的工具依賴。使用工具類操作還是很簡潔友善的。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.7</version>
</dependency>
import cn.hutool.core.io.FileUtil;//需要引入這個、引入不對、無法使用對應的方法
/**
* @author Lenovo
* @version 1.0
* @data 2022/10/11 21:32
*/
@RestController
public class GoodsfileInfoController {
@Autowired
GoodsFileInfoMapper gfMapper;
private static final String ABSOLUTE_FILE_PATH = "E:\\Lenovo\\Documents\\upload\\images\\";
/**
* 檔案上傳 絕對
* @param file
* @return
*/
@RequestMapping(value = "/goodsInfo/upload",method = RequestMethod.POST)
public Result upload(MultipartFile file, HttpServletRequest request) throws IOException {
String originName = file.getOriginalFilename();
// 1、檔案名加個時間戳
String fileName = FileUtil.mainName(originName) + System.currentTimeMillis() + "." + FileUtil.extName(originName);
// 2、檔案存放的絕對路徑 存放名稱
String storageName = ABSOLUTE_FILE_PATH + fileName;
// 3. 檔案上傳
FileUtil.writeBytes(file.getBytes(),storageName );
String final_fileName ="http://localhost:8282/images/" + fileName;
return Result.ok().data("fileName",final_fileName);
}
}
<hr>
2.2.2 一般的操作
2.2.1 和 2.2.2 可以自行選擇使用、實作的效果是一樣的
一般的檔案寫入操作、這個對檔案名的處理還是使用的工具類。自己也可以根據自己的要求、自行處理檔案名
/**
* @author Lenovo
* @version 1.0
* @data 2022/10/11 21:32
*/
@RestController
public class GoodsfileInfoController {
@Autowired
GoodsFileInfoMapper gfMapper;
private static final String ABSOLUTE_FILE_PATH = "E:\\Lenovo\\Documents\\upload\\images\\";
/**
* 檔案上傳 絕對
* @param file
* @return
*/
@RequestMapping(value = "/goodsInfo/upload",method = RequestMethod.POST)
public Result upload(MultipartFile file, HttpServletRequest request) throws IOException {
System.out.println(System.getProperty("user.dir"));
String originName = file.getOriginalFilename();
// 1、檔案名加個時間戳
String fileName = FileUtil.mainName(originName) + System.currentTimeMillis() + "." + FileUtil.extName(originName);
System.out.println(fileName);
// 2、檔案存放的絕對路徑 存放名稱
String storageName = ABSOLUTE_FILE_PATH + fileName;
// 3. 檔案上傳
File dest = new File(storageName);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest);
} catch (IOException e) {
e.printStackTrace();
}
String final_fileName ="http://localhost:8282/images/" + fileName;
return Result.ok().data("fileName",final_fileName);
}
}
2.3 檢視傳回給前端的圖檔位址
2.4 前端儲存後端傳回的圖檔位址
2.5 檢視存儲到資料庫中的圖檔資源位址
這裡存放的不是圖檔在磁盤中的絕對路徑、需要做圖檔資源映射使用的
2.6 存到對應磁盤位置的圖檔
3、後端配置
3.1 圖檔資源映射
這裡給出使用java代碼的形式盡心資源映射、下一篇優化在配置檔案中進行配置
/**
* @author Lenovo
* @version 1.0
* @data 2022/10/12 18:58
*/
@Configuration
public class URLConfig implements WebMvcConfigurer {
/**
* * 資源映射路徑
* * addResourceHandler:通路映射路徑
* * addResourceLocations:資源絕對路徑
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations("file:"+"E:\\Lenovo\\Documents\\upload\\images\\");
}
}
3.2 如果設定了token、要放行圖檔資源。否則攔截
3.3 如果圖檔資源帶有中文導緻的圖檔資源通路不到、配置過濾器、設定編碼格式
package com.zyz.bookshopmanage.config;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URLDecoder;
/**
* @author Lenovo
* @version 1.0
* @data 2022/10/12 23:04
*/
@Configuration
public class UrlFilter implements Filter {
public final static String DEFAULT_URI_ENCODE = "UTF-8";
private FilterConfig config = null;
private String encode = null;
@Override
public void destroy() {
config = null;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
String uri = request.getRequestURI();
String ch = URLDecoder.decode(uri, encode);
if(uri.equals(ch)) {
chain.doFilter(req, res);
return;
}
ch = ch.substring(request.getContextPath().length());
config.getServletContext().getRequestDispatcher(ch).forward(req, res);
}
@Override
public void init(FilterConfig config) throws ServletException {
this.config = config;
this.encode = config.getInitParameter("DEFAULT_URI_ENCODE");
if(this.encode == null) {
this.encode = DEFAULT_URI_ENCODE;
}
}
}
4、圖檔的回顯
圖檔回顯的方式和種類蠻多、我這邊想要實作的效果、是點選按鈕來展示對應的圖檔。你也可以直接将圖檔放到表格中
在商品資訊界面、點選預覽,将對應商品的圖檔彈窗的形式展示出來
4.1 前端代碼
<el-table-column label="商品圖檔">
<template slot-scope="scopes">
<button
class="btn btn-primary btn-xs"
@click="showImage(scopes.$index, scopes.row)"
>
預覽
</button>
</template>
</el-table-column>
//檔案顯示
showImage: function (index, row) {
console.log(row.fileName);
const myimgUrl = row.fileName;
this.dialogVisibleImage = true;
this.$nextTick(function () {
//擷取元素
$("#view-img").empty();
$("#view-img").append(
$(
`<img src="${myimgUrl}" style="width: 400px; margin-bottom: 5px" alt="">`
)
);
});
},
<el-dialog
title="檔案預覽"
:visible.sync="dialogVisibleImage"
width="30%"
:before-close="handleClose"
>
<div
id="view-img"
class="modal-body"
style="text-align: center"
></div>
</el-dialog>