element的el-upload組件上傳文件跨域問題的幾種解決
前言
最近在開發(fā)基于 SpringBoot 和 Vue 的前后端分離項目的時候,在使用 element-ui 的 el-upload 組件的時候遇到了跨域的問題,盡管之前我也寫過一篇關(guān)于解決跨域問題的文章,但是發(fā)現(xiàn)還是無法解決使用 action 時的跨域問題,因此本文將基于后端 SpringBoot 和 基于 nginx 反向代理的解決跨域的方法,本文的完整代碼(前端和后端代碼)也已上傳到GitHub。
使用 action 的解決方法
在具體的講解之前先聲明,本文的后端都基于 8888 端口,前端基于 8080 端接口,nginx 代理端口為 80。下面是前端使用 el-upload的代碼,為了方便專注于跨域問題,已去掉不必要的屬性:
<el-upload class="upload-demo" action="http://localhost/nginx/uploadByAction" :file-list="fileList"> <el-button size="small" type="primary">點擊上傳</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 "上傳失敗,請選擇文件";
}
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;
}
只要以上簡單的 nginx 配置便解決了使用 ation 時的跨域問題,相信看過前言里我說的解決跨域問題的那篇文章的同學(xué)會發(fā)現(xiàn),這里的nginx 配置只是多了下面這句:
if ($request_method = 'OPTIONS') {
return 204;
}
這里是因為使用 action 時,會發(fā)送一個預(yù)檢請求,關(guān)于預(yù)檢請求的詳細介紹,可以查看這篇文章,這里的配置主要是為了讓預(yù)檢請求正常的返回,其實仔細查看點擊了上傳時的Network,就會后臺其實發(fā)送了兩個請求:


基于 SpringBoot 后臺代碼的解決方法
其實基于 SpringBoot 后臺代碼的解決方法也就是將上述的 nginx 反向代理配置改成了具體的代碼配置而已,下面就具體介紹,首先由于現(xiàn)在不再使用反向代理了,el-upload 里的 action 屬性也需要改為 http://localhost:8888/springboot/uploadByAction,然后就是后臺代碼的改變:
首先是 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 "上傳失敗,請選擇文件";
}
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 反向代理的配置,也可以直接訪問 8888 端口請求資源了。
不使用 action 的解決方法
下面再講講不使用 action 的解決方法,其實還是推薦不使用 action,自己處理 ajax 請求可以更自由一些。
首先是前端的代碼:
<el-upload class="upload-demo" action="" :http-request="upload"> <el-button size="small" type="primary">點擊上傳</el-button> </el-upload>
由于不再使用 action,因此這里的值任意,http-request 里的值對應(yīng)自己處理請求的方法,upload 方法如下(使用了 axios 發(fā)送 ajax 請求):
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('圖片上傳失敗')
})
}
對應(yīng)的后臺處理的 controller 代碼如下:
@RestController
public class UploadWithoutAction {
@Value("${upload.filePath}")
private String filePath;
@PostMapping("/uploadWithoutAction")
public String upload(@RequestPart("file") MultipartFile file) {
if (file.isEmpty()) {
return "上傳失敗,請選擇文件";
}
String fileName = file.getOriginalFilename();
File dest = new File(filePath + fileName);
try {
file.transferTo(dest);
return "上傳成功";
} catch (IOException e) {
e.printStackTrace();
return "上傳失敗";
}
}
}
由于在使用 action 的解決方法里已經(jīng)配置過攔截器設(shè)置了 response.addHeader("Access-Control-Allow-Origin", "*"); 這里就不再需要配置跨域了,如果想通過 nginx 反向代理解決跨域,以上的攔截器都不要設(shè)置,然后把上文中 nginx 反向代理配置中的關(guān)于 OPTIONS 的處理配置去掉即可,當(dāng)然不去掉也沒什么影響,如果不使用 action 了,參考我前言里的處理跨域的那篇文章即可。
總結(jié)
本文簡單介紹了如何處理使用 el-upload 的 action 時的跨域問題,其實本質(zhì)還是解決 OPTIONS 的預(yù)檢請求請求問題。
到此這篇關(guān)于element的el-upload組件上傳文件跨域問題的幾種解決的文章就介紹到這了,更多相關(guān)element el-upload 上傳跨域內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue-element-admin如何設(shè)置默認語言
這篇文章主要介紹了vue-element-admin如何設(shè)置默認語言,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04

