当前位置: 首页 > news >正文

element-ui 源码调用接口跨域问题

今天在看 upload 组件源码时,在组件源码当中调用的本地启动的 nodejs 服务写的上传接口,遇到跨域问题:

问题一、在 upload.md 中调用 nodejs 服务中的 上传接口,控制台报跨域报错。

解决方法1:在根目录增加 vue.config.js 文件,解决控制台报错。

module.exports = {devServer: {proxy: {'/api': {target: 'http://localhost:3000', // 后端地址changeOrigin: true,pathRewrite: {'^/api' : '/api'},}}}
};

问题二、基于上面的问题,控制台不再报错后,接口一直 404。

解决方法1:nodejs 增加 cor 组件,前端代码中使用域名+接口的形式调用,可以正常调用接口:

const Koa = require('koa');
const serve = require('koa-static');
const path = require('path');
const fs = require('fs').promises; // 使用 promises 版本的 fs
const { koaBody } = require('koa-body');
const jsonError = require('koa-json-error');
const parameter = require('koa-parameter');
const koajwt = require('koa-jwt');
const cors = require('@koa/cors'); // 新增:CORS 支持const { connectDB } = require('./db/index.js');const user = require('./routes/user.js');
const department = require('./routes/department.js');
const departmentApplication = require('./routes/departmentApplication.js');
const certificate = require('./routes/certificate.js');
const post = require('./routes/post.js');
const userApplication = require('./routes/userApplication.js');
const menu = require('./routes/menu.js');const app = new Koa();// ===== 添加 CORS 中间件 =====
app.use(cors({origin: 'http://localhost:8085', // 修改为你的前端地址credentials: true, // 允许携带 cookies 或 tokenallowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],allowHeaders: ['Content-Type', 'Authorization'],})
);// 静态资源中间件
app.use(serve(path.join(__dirname, 'uploads'))); // 上传文件目录
app.use(serve(path.join(__dirname, 'public'), { prefix: '/static' })); // 公共静态资源目录// 处理根路径和 favicon.ico 请求
app.use(async (ctx, next) => {if (ctx.request.url === '/') {ctx.body = '<h1>Welcome to the Koa server</h1>';return;}if (ctx.request.url === '/favicon.ico') {ctx.type = 'image/x-icon';try {ctx.body = await fs.readFile(path.join(__dirname, 'public', 'favicon.ico'));} catch (err) {ctx.status = 404;ctx.body = 'Favicon not found';}return;}await next();
});// JWT 校验中间件
app.use(koajwt({secret: 'jqh-server-jwt',}).unless({path: [/^\/api\/user\/login/, // 登录页面不做权限控制/^\/static\//, // public下的 static 开头的资源不做权限控制/^\/favicon\.ico$/, // favicon.ico 图标不做权限控制],})
);// 错误处理、body 解析、参数校验中间件
app.use(jsonError());
app.use(koaBody({multipart: true, // 支持文件上传formidable: {maxFileSize: 2000 * 1024 * 1024, // 限制文件上传大小,例如2GB},})
);
app.use(parameter(app));// 连接数据库
connectDB();// 注册路由
app.use(user.routes()).use(user.allowedMethods());
app.use(department.routes()).use(department.allowedMethods());
app.use(departmentApplication.routes()).use(departmentApplication.allowedMethods());
app.use(certificate.routes()).use(certificate.allowedMethods());
app.use(post.routes()).use(post.allowedMethods());
app.use(userApplication.routes()).use(userApplication.allowedMethods());
app.use(menu.routes()).use(menu.allowedMethods());// 监听端口
app.listen(3000, () => {console.log('Server is running on http://localhost:3000');
});

 前端部分:

<template><div><el-uploadref="uploadRef":auto-upload="false":on-change="handleAvatarChange":show-file-list="false"class="upload-avatar-wrapper"accept="image/*":action="uploadUrl"><imgv-if="form.avatar":src="form.avatar"class="avatar"style="width:60px;height:60px;text-align:center;line-height:60px;border:1px #ddd solid;"/><divv-elseclass="avatar-uploader-icon"style="width:60px;height:60px;text-align:center;line-height:60px;border:1px #ddd solid;"><i class="el-icon-plus"></i></div></el-upload><el-button @click="customUpload">上传</el-button></div>
</template><script>export default {data() {return {token:'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVyQ29kZSI6InN1cGVyMDAxIiwiaWF0IjoxNzQ3MTE5NjEzLCJleHAiOjE3NDc3MjQ0MTN9.YQBUW1nt8MtVaTUE-sJ8R78h9ngbnzjmLZRk4kkUMHU',form: {operName: 'super001',password: '123456',avatar: '',},selectedFile: null,uploadUrl: 'http://localhost:3000/api/user/uploadAvatar',};},methods: {// 文件选择变化时handleAvatarChange(file) {const reader = new FileReader();reader.onload = (e) => {this.form.avatar = e.target.result; // 正确赋值};if (file.raw) {reader.readAsDataURL(file.raw);this.selectedFile = file.raw;}},// 自定义上传方法(由按钮触发)customUpload() {if (!this.selectedFile) {this.$message.warning('请先选择一个文件');return;}const formData = new FormData();formData.append('operName', this.form.operName);formData.append('password', this.form.password);formData.append('avatar', this.selectedFile);fetch(this.uploadUrl, {method: 'POST',headers: {Authorization: `Bearer ${this.token}`,},body: formData,credentials: 'include',}).then((response) => {if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}return response.json();}).then((data) => {console.log('Success:', data);this.selectedFile = null;this.$message.success('上传成功');}).catch((error) => {console.error('Error:', error);this.$message.error('上传失败');});},},};
</script><style>/* 样式部分保持不变 */.upload-avatar-wrapper {width: 60px;height: 60px;border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;display: flex;justify-content: center;align-items: center;}.upload-avatar-wrapper:hover {border-color: #409eff;}.avatar-uploader-icon {font-size: 28px;}.avatar {width: 100%;height: 100%;object-fit: cover;}
</style>

解决方法2:使用的是 npm run dev 启动的项目,通过 package.json 可以看到所使用的 webpack 配置文件。

找到 webpack.demo.js 配置文件:

后端 nodejs 代码不用使用 cor 组件,前端代码如下:

<template><div><el-uploadref="uploadRef":auto-upload="false":on-change="handleAvatarChange":show-file-list="false"class="upload-avatar-wrapper"accept="image/*":action="uploadUrl"><imgv-if="form.avatar":src="form.avatar"class="avatar"style="width:60px;height:60px;text-align:center;line-height:60px;border:1px #ddd solid;"/><divv-elseclass="avatar-uploader-icon"style="width:60px;height:60px;text-align:center;line-height:60px;border:1px #ddd solid;"><i class="el-icon-plus"></i></div></el-upload><el-button @click="customUpload">上传</el-button></div>
</template><script>export default {data() {return {token:'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcGVyQ29kZSI6InN1cGVyMDAxIiwiaWF0IjoxNzQ3MTE5NjEzLCJleHAiOjE3NDc3MjQ0MTN9.YQBUW1nt8MtVaTUE-sJ8R78h9ngbnzjmLZRk4kkUMHU',form: {operName: 'super001',password: '123456',avatar: '',},selectedFile: null,uploadUrl: '/api/user/uploadAvatar',};},methods: {// 文件选择变化时handleAvatarChange(file) {const reader = new FileReader();reader.onload = (e) => {this.form.avatar = e.target.result; // 正确赋值};if (file.raw) {reader.readAsDataURL(file.raw);this.selectedFile = file.raw;}},// 自定义上传方法(由按钮触发)customUpload() {if (!this.selectedFile) {this.$message.warning('请先选择一个文件');return;}const formData = new FormData();formData.append('operName', this.form.operName);formData.append('password', this.form.password);formData.append('avatar', this.selectedFile);fetch(this.uploadUrl, {method: 'POST',headers: {Authorization: `Bearer ${this.token}`,},body: formData,credentials: 'include',}).then((response) => {if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}return response.json();}).then((data) => {console.log('Success:', data);this.selectedFile = null;this.$message.success('上传成功');}).catch((error) => {console.error('Error:', error);this.$message.error('上传失败');});},},};
</script><style>/* 样式部分保持不变 */.upload-avatar-wrapper {width: 60px;height: 60px;border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;display: flex;justify-content: center;align-items: center;}.upload-avatar-wrapper:hover {border-color: #409eff;}.avatar-uploader-icon {font-size: 28px;}.avatar {width: 100%;height: 100%;object-fit: cover;}
</style>

 

总结:建议使用前端增加反向代理的方式。产生问题的原因,对源码当中的项目启动配置不熟悉,想当然的增加 vue.config.js 配置,以为可以解决问题,行不通时,考虑从后端代码解决问题。问题解决完成之后,已经有了退路,冷静下来寻找问题的原因,发现启动脚本 npm run dev 中使用的 build 文件夹下的 webpack.demo.js 配置,在这个配置中增加反向代理并重启后,跨域问题解决。

相关文章:

  • 第二十三天打卡
  • 无缝对接主流电商平台接口,解决货源难题
  • Java SpringMVC 和 MyBatis 整合项目的事务管理配置详解
  • 在Linux系统中开放指定端口访问(允许远程访问数据库)
  • [Java][Leetcode middle] 55. 跳跃游戏
  • Ansys 计算刚柔耦合矩阵系数
  • leetcode 189. 轮转数组
  • 制造业AI质量检测方案
  • 【Qt】之音视频编程1:QtAV的背景和安装篇
  • GTS-400 系列运动控制器板卡介绍(二十五)---PVT 描述方式
  • 【应用密码学】实验五 公钥密码2——ECC
  • OJ判题系统第6期之判题逻辑开发——设计思路、实现步骤、代码实现(策略模式)
  • talk-centos6之间实现
  • c语言第一个小游戏:贪吃蛇小游戏07
  • go语言学习进阶
  • 基于MATLAB的生物量数据拟合模型研究
  • linux中fork()函数的小问题
  • 多模态RAG与LlamaIndex——1.deepresearch调研
  • SpringBoot的单体和分布式的任务架构
  • 项目三 - 任务6:回文日期判断
  • 李强会见巴西总统卢拉
  • 图讯丨习近平出席中国-拉美和加勒比国家共同体论坛第四届部长级会议开幕式
  • 中央结算公司:减免境外央行类机构账户开户费用
  • 新华时评:中美经贸会谈为全球经济纾压增信
  • 长沙查处疑似非法代孕:有人企图跳窗,有女子被麻醉躺手术台
  • 季后赛主场优势消失之谜,这事竟然要赖库里