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-04vue實(shí)現(xiàn)抽獎(jiǎng)效果Demo
這篇文章主要介紹了vue實(shí)現(xiàn)抽獎(jiǎng)效果Demo,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01VueUse功能精簡(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