今日記錄通過elementui上傳時得到的問題。
我們在本地部署的服務(wù),前端服務(wù)請求后端接口,存在跨域問題,
至于為什么會有跨域這個問題?
跨域問題確實是由Web瀏覽器的同源策略引起的。同源策略是瀏覽器的一項安全機(jī)制,它限制了從一個源加載的文檔或腳本如何與來自其他源的資源進(jìn)行交互。
同源策略要求在以下三個方面完全匹配時才被認(rèn)為是同源:
- 協(xié)議(Protocol):兩個頁面的協(xié)議必須相同(如都是http或https)。
- 域名(Domain):兩個頁面的域名必須相同,包括子域名(如example.com和www.example.com被視為不同的域名)。
- 端口號(Port):兩個頁面的端口號必須相同(如果指定了端口號)。
為什么后端服務(wù)跟后端服務(wù)的交互,沒有跨域;而瀏覽器和服務(wù)器的交互有?
因為,后端服務(wù)之間不存在同源策略的限制。
另外,我們通常前端向后端的通信請求,一般依賴的是瀏覽器的通信API來完成的,當(dāng)我們請求時,瀏覽器會檢測我們請求的url是否與當(dāng)前存在跨域問題。
解決跨域:
1.可以利用springboot解決跨域問題,這里不列舉
2.利用vue配置進(jìn)行反向代理。
vue解決跨域
在vue.config.js文件中配置
module.exports = {
devServer: {
proxy: {
'/api': { // 請求的代稱,寫在Axios里的BaseUrl
target: 'http://localhost:8088', // 真實請求URl
ws: true,
changeOrigin: true, // 允許跨域
pathRewrite: { //替換,通配/api的替換成對應(yīng)字符
// /* 重寫路徑,當(dāng)我們在瀏覽器中看到請求的地址為:http://localhost:8080/api/core/getData/userInfo 時
// 實際上訪問的地址是:http://localhost:8088/core/getData/userInfo,因為重寫了 /api
// */
'^/api': '' //當(dāng)你的接口中沒有/api字眼時,采用這種,直接替換成空即可
// '^/api': '/api' //當(dāng)你的接口中剛好有/api 時,采用這種方式
}
}
}
}
}
換句話說,在本地創(chuàng)建了一個代理服務(wù)器,我們的請求全發(fā)到代理服務(wù)器上了?,由代理服務(wù)器替我們發(fā)請求到后端服務(wù)器,拿到響應(yīng)數(shù)據(jù)接著響應(yīng)給我。
圖片上傳
java代碼如下:
@RestController
@RequestMapping("/common")
@Api(tags = "文件controller")
public class CommonController {
@Value("${reggie.path}")
private String basePath;
@ApiOperation("文件上傳")
@PostMapping("/upload")
public Result upLoad(@RequestParam("file") MultipartFile file) {
// 原始文件名 abc.jpc
String originalFilename = file.getOriginalFilename();
// 獲取文件類型(jpg、png) .jpc
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
// 使用UUID重新生成文件名,防止文件名重復(fù)
String fileName = UUID.randomUUID() + suffix;
// 創(chuàng)建目錄
File dir = new File(basePath);
if(!dir.exists()) {
dir.mkdirs();
}
try {
file.transferTo(new File(basePath + fileName)); // 當(dāng)前目錄下,生成圖片,我們將這個路徑返回
} catch (IOException e) {
e.printStackTrace();
}
return Result.success("文件上傳成功", fileName);
}
@ApiOperation("文件下載")
@GetMapping("/download")
public void downLoad(String name, HttpServletResponse response) {
try {
// 輸入流,通過輸入流讀取文件內(nèi)容
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();
}
//關(guān)閉資源
outputStream.close();
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
?
vue代碼如下:
<el-upload action="/api/common/upload" //后端請求上傳圖片接口
list-type="picture-card"
:show-file-list="false" // 開啟上傳圖片列表
:on-success="handleAvatarSuccess" // 成功響應(yīng)后調(diào)用api,主要是這個
:before-upload="beforeAvatarUpload" //上傳之前調(diào)用api
>
<i class="el-icon-plus"></i>
</el-upload>
<img :src="infoForm.avatar" alt="編輯頭像" class="update-img">
我們后端指定上傳圖片路徑如上,當(dāng)我們點擊上傳圖片時,請求后端接口,圖片會緩存到上述位置 ,并且會被如下函數(shù)接收到。
// 獲得上傳圖片的url
handleAvatarSuccess(res, file) {
console.log(file, res);
this.infoForm.avatar = 'images/' + res.data
// 拿到二進(jìn)制數(shù)據(jù),是blob類型,存儲到瀏覽器內(nèi)存中,一刷新數(shù)據(jù)會消失
// console.log("imgUrl:", URL.createObjectURL(file.raw));
},
具體接受結(jié)果。?
以上,我們可以2種方式,拿到圖片url:
- ?獲取blob,url,但是一刷新圖片會消失,因為blob url表示的圖片是在瀏覽器內(nèi)存中,而不是存儲在硬盤上。
- ?利用images/?+ 圖片名字.jpg
具體就是: 我們后端緩存路徑就是,vue項目中的public/images文件夾。
為什么這樣使用呢?
淺談一下:
1.經(jīng)過webpack打包的vue項目結(jié)構(gòu)會發(fā)生改變,我們原有的圖片路徑會失效。
2.public文件下,相當(dāng)于是靜態(tài)資源,不會經(jīng)過webpack打包。
3.vue對于靜態(tài)路徑和動態(tài)路徑(變量)的解析不一樣。
具體看如下:文章來源:http://www.zghlxwxcb.cn/news/detail-693817.html
vue圖片路徑問題_本郡主是喵的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-693817.html
到了這里,關(guān)于springboot + vue + elementui — upload解決跨域、實現(xiàn)圖片上傳的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!