element的el-upload組件上傳文件跨域問(wèn)題的幾種解決
前言
最近在開(kāi)發(fā)基于 SpringBoot 和 Vue 的前后端分離項(xiàng)目的時(shí)候,在使用 element-ui 的 el-upload 組件的時(shí)候遇到了跨域的問(wèn)題,盡管之前我也寫(xiě)過(guò)一篇關(guān)于解決跨域問(wèn)題的文章,但是發(fā)現(xiàn)還是無(wú)法解決使用 action 時(shí)的跨域問(wèn)題,因此本文將基于后端 SpringBoot 和 基于 nginx 反向代理的解決跨域的方法,本文的完整代碼(前端和后端代碼)也已上傳到GitHub。
使用 action 的解決方法
在具體的講解之前先聲明,本文的后端都基于 8888 端口,前端基于 8080 端接口,nginx 代理端口為 80。下面是前端使用 el-upload的代碼,為了方便專注于跨域問(wèn)題,已去掉不必要的屬性:
<el-upload class="upload-demo" action="http://localhost/nginx/uploadByAction" :file-list="fileList"> <el-button size="small" type="primary">點(diǎn)擊上傳</el-button> </el-upload>
下面是后端的配置文件(application.yaml)代碼:
server: port: 8888 upload: filePath: D:\\Temp\\img\\
基于 nginx 反向代理的解決方法
后端接口代碼如下:
@RestController
public class UploadByAction {
@Value("${upload.filePath}")
private String filePath;
@PostMapping("/nginx/uploadByAction")
public String uploadByNginx(@RequestPart("file") MultipartFile file) {
return getUploadMsg(file);
}
private String getUploadMsg(@RequestPart("file") MultipartFile file) {
if (file.isEmpty()) {
return "上傳失敗,請(qǐng)選擇文件";
}
String fileName = file.getOriginalFilename();
File dest = new File(filePath + fileName);
try {
file.transferTo(dest);
return "上傳成功";
} catch (IOException e) {
e.printStackTrace();
return "上傳失敗";
}
}
}
nginx 代理配置如下:
location / {
root html;
add_header Access-Control-Allow-Origin *;
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://localhost:8888;
index index.html index.htm;
}
只要以上簡(jiǎn)單的 nginx 配置便解決了使用 ation 時(shí)的跨域問(wèn)題,相信看過(guò)前言里我說(shuō)的解決跨域問(wèn)題的那篇文章的同學(xué)會(huì)發(fā)現(xiàn),這里的nginx 配置只是多了下面這句:
if ($request_method = 'OPTIONS') {
return 204;
}
這里是因?yàn)槭褂?nbsp;action 時(shí),會(huì)發(fā)送一個(gè)預(yù)檢請(qǐng)求,關(guān)于預(yù)檢請(qǐng)求的詳細(xì)介紹,可以查看這篇文章,這里的配置主要是為了讓預(yù)檢請(qǐng)求正常的返回,其實(shí)仔細(xì)查看點(diǎn)擊了上傳時(shí)的Network,就會(huì)后臺(tái)其實(shí)發(fā)送了兩個(gè)請(qǐng)求:


基于 SpringBoot 后臺(tái)代碼的解決方法
其實(shí)基于 SpringBoot 后臺(tái)代碼的解決方法也就是將上述的 nginx 反向代理配置改成了具體的代碼配置而已,下面就具體介紹,首先由于現(xiàn)在不再使用反向代理了,el-upload 里的 action 屬性也需要改為 http://localhost:8888/springboot/uploadByAction,然后就是后臺(tái)代碼的改變:
首先是 controller 接口的代碼:
@RestController
public class UploadByAction {
@Value("${upload.filePath}")
private String filePath;
@PostMapping("/springboot/uploadByAction")
public String uploadBySpringBoot(@RequestPart("file") MultipartFile file) {
return getUploadMsg(file);
}
private String getUploadMsg(@RequestPart("file") MultipartFile file) {
if (file.isEmpty()) {
return "上傳失敗,請(qǐng)選擇文件";
}
String fileName = file.getOriginalFilename();
File dest = new File(filePath + fileName);
try {
file.transferTo(dest);
return "上傳成功";
} catch (IOException e) {
e.printStackTrace();
return "上傳失敗";
}
}
}
然后是攔截器的設(shè)置:
@Configuration
public class CorsInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(
HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.addHeader("Access-Control-Allow-Origin", "*");
if ("OPTIONS".equals(request.getMethod())) {
return true;
}
return HandlerInterceptor.super.preHandle(request, response, handler);
}
}
最后添加攔截器:
@Configuration
public class ApiConfig extends WebMvcConfigurationSupport {
private final CorsInterceptor corsInterceptor;
@Autowired
public ApiConfig(CorsInterceptor corsInterceptor) {
this.corsInterceptor = corsInterceptor;
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(corsInterceptor).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
完成以上配置后便不再需要使用 nginx 反向代理的配置,也可以直接訪問(wèn) 8888 端口請(qǐng)求資源了。
不使用 action 的解決方法
下面再講講不使用 action 的解決方法,其實(shí)還是推薦不使用 action,自己處理 ajax 請(qǐng)求可以更自由一些。
首先是前端的代碼:
<el-upload class="upload-demo" action="" :http-request="upload"> <el-button size="small" type="primary">點(diǎn)擊上傳</el-button> </el-upload>
由于不再使用 action,因此這里的值任意,http-request 里的值對(duì)應(yīng)自己處理請(qǐng)求的方法,upload 方法如下(使用了 axios 發(fā)送 ajax 請(qǐng)求):
upload(param) {
const formData = new FormData()
formData.append('file', param.file)
const url = 'http://localhost:8888/uploadWithoutAction'
axios.post(url, formData).then(data => {
console.log('上傳圖片成功')
}).catch(response => {
console.log('圖片上傳失敗')
})
}
對(duì)應(yīng)的后臺(tái)處理的 controller 代碼如下:
@RestController
public class UploadWithoutAction {
@Value("${upload.filePath}")
private String filePath;
@PostMapping("/uploadWithoutAction")
public String upload(@RequestPart("file") MultipartFile file) {
if (file.isEmpty()) {
return "上傳失敗,請(qǐng)選擇文件";
}
String fileName = file.getOriginalFilename();
File dest = new File(filePath + fileName);
try {
file.transferTo(dest);
return "上傳成功";
} catch (IOException e) {
e.printStackTrace();
return "上傳失敗";
}
}
}
由于在使用 action 的解決方法里已經(jīng)配置過(guò)攔截器設(shè)置了 response.addHeader("Access-Control-Allow-Origin", "*"); 這里就不再需要配置跨域了,如果想通過(guò) nginx 反向代理解決跨域,以上的攔截器都不要設(shè)置,然后把上文中 nginx 反向代理配置中的關(guān)于 OPTIONS 的處理配置去掉即可,當(dāng)然不去掉也沒(méi)什么影響,如果不使用 action 了,參考我前言里的處理跨域的那篇文章即可。
總結(jié)
本文簡(jiǎn)單介紹了如何處理使用 el-upload 的 action 時(shí)的跨域問(wèn)題,其實(shí)本質(zhì)還是解決 OPTIONS 的預(yù)檢請(qǐng)求請(qǐng)求問(wèn)題。
到此這篇關(guān)于element的el-upload組件上傳文件跨域問(wèn)題的幾種解決的文章就介紹到這了,更多相關(guān)element el-upload 上傳跨域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue-element-admin如何設(shè)置默認(rèn)語(yǔ)言
這篇文章主要介紹了vue-element-admin如何設(shè)置默認(rèn)語(yǔ)言,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue實(shí)現(xiàn)抽獎(jiǎng)效果Demo
這篇文章主要介紹了vue實(shí)現(xiàn)抽獎(jiǎng)效果Demo,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
VueUse功能精簡(jiǎn)你的dependencies
這篇文章主要為大家介紹了VueUse功能精簡(jiǎn)你的dependencies實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
在Vue項(xiàng)目中優(yōu)化字體文件的加載和緩存的常用方法
在現(xiàn)代 Web 開(kāi)發(fā)中,字體文件通常是頁(yè)面加載時(shí)間的重要因素之一,特別是在字體文件較大或網(wǎng)絡(luò)環(huán)境不佳的情況下,用戶體驗(yàn)可能會(huì)受到影響,本文將詳細(xì)探討如何在 Vue.js 項(xiàng)目中優(yōu)化字體文件的加載和緩存,以提高頁(yè)面性能,需要的朋友可以參考下2024-09-09

