前端 Vue 对接 UNet 后端:跨域 CORS 配置方案
1. 教程目标与背景
在开发前端项目时,常需调用基于 UNet 人像卡通化模型的后端服务。此类服务通常基于 Gradio 框架搭建,默认监听在 localhost:7860 端口。而 Vue 项目通常运行在 或 端口上,导致浏览器直接报错:
解决 Vue 前端调用 UNet 后端(基于 Gradio)时的跨域问题。介绍了三种方案:一是利用 vue.config.js 设置开发服务器代理,适合本地调试;二是在后端 launch 参数中启用 enable_cors=True 或配置 FastAPI CORS 中间件,适合长期生产使用;三是通过 Nginx 反向代理统一入口。文章提供了具体的代码示例、接口路径确认方法及错误处理建议,帮助开发者打通前后端通信链路,实现图片上传与卡通化结果展示。
在开发前端项目时,常需调用基于 UNet 人像卡通化模型的后端服务。此类服务通常基于 Gradio 框架搭建,默认监听在 localhost:7860 端口。而 Vue 项目通常运行在 或 端口上,导致浏览器直接报错:
localhost:80803000Access to fetch at 'http://localhost:7860/predict' from origin 'http://localhost:8080' has been blocked by CORS policy.
本教程将介绍如何让 Vue 前端顺利调用 UNet 后端 API,完成图片上传、卡通化处理及结果获取的完整流程。
人像卡通化系统基于 Gradio 框架启动,默认监听地址为:
http://localhost:7860
它提供图形界面并暴露底层 API 接口(如 /predict),允许外部程序通过 HTTP 请求提交图片并获取处理结果。由于不同端口且后端未启用 CORS 支持,浏览器会拦截跨域请求。
交互逻辑如下:
Vue 前端 (http://localhost:8080) -> 上传图片 -> 调用后端 API (http://localhost:7860/predict) -> 返回 base64 或文件路径 -> 显示卡通化结果 + 提供下载
关键在于打通跨域限制。
| 方式 | 是否推荐 | 说明 |
|---|---|---|
| 开发服务器代理(vue.config.js) | ✅ 推荐新手 | 利用 Vue CLI 内置代理转发请求 |
| 修改后端启用 CORS | ✅ 推荐生产环境 | 直接在 Python 服务中开启跨域支持 |
| 使用 Nginx 反向代理 | ⚠️ 进阶可用 | 更稳定,适合部署上线 |
若使用 Vue CLI 创建的项目,可通过修改 vue.config.js 设置代理。
在项目根目录下创建文件:
// vue.config.js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:7860',
changeOrigin: true,
pathRewrite: {
'^/api': '' // 把 /api 替换为空,转发到根路径
}
}
}
}
}
注意:修改后需要重启
npm run serve才能生效。
现在可以通过 /api/predict 访问原本的 http://localhost:7860/predict 接口。
示例代码(使用 axios):
// App.vue 或组件中
import axios from 'axios'
export default {
methods: {
async convertImage(file) {
const formData = new FormData()
formData.append('image', file)
try {
const response = await axios.post('/api/predict', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
// 假设返回的是 base64 图片数据
this.resultImage = 'data:image/png;base64,' + response.data.output_image
} catch (error) {
console.error('转换失败:', error)
alert('调用后端失败,请检查服务是否运行')
}
}
}
}
打开浏览器开发者工具 Network 面板:
http://localhost:8080/api/predicthttp://localhost:7860/predict✅ 优点:无需改后端,零成本接入 ❌ 缺点:仅限开发环境,打包后无效
更根本的解决方案是在 UNet 后端服务中开启 CORS 支持。
服务通常由以下命令启动:
/bin/bash /root/run.sh
我们需要找到调用的 Python 文件,通常是 app.py 或 gradio_app.py。
只需在 launch() 中加入 enable_cors=True 参数即可:
import gradio as gr
def cartoonize(img):
# 模型推理逻辑
return result_img
demo = gr.Interface(fn=cartoonize, inputs="image", outputs="image")
demo.launch(
server_name="0.0.0.0",
server_port=7860,
enable_cors=True # 允许跨域请求
)
或者配合 FastAPI 的 CORS 中间件:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:8080"], # 明确允许前端域名
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
执行启动脚本确保服务重新加载新配置。然后在 Vue 中直接请求真实地址,不再出现跨域错误。
✅ 优点:一劳永逸,支持任意前端 ❌ 缺点:需修改后端代码,有一定风险
项目上线时,建议使用 Nginx 统一管理前后端入口。
server {
listen 80;
server_name yourdomain.com;
# 前端静态资源
location / {
root /var/www/vue-app;
try_files $uri $uri/ /index.html;
}
# 代理后端 API
location /unet-api/ {
rewrite ^/unet-api/(.*)$ /$1 break;
proxy_pass http://127.0.0.1:7860;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
await axios.post('/unet-api/predict', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
所有请求都会被 Nginx 自动转发到本地 7860 端口。
✅ 优点:安全、统一入口、便于部署 ❌ 缺点:需要服务器权限,配置稍复杂
Gradio 默认的预测接口可能是:
/api/predict(新版)/run(旧版)/predict(某些封装版本)建议先打开 WebUI 页面,右键检查源码或使用开发者工具观察 Network 面板发出的请求。
Gradio 接口通常接收 JSON 格式,例如:
{
"data": ["data:image/jpeg;base64,/9j/4AAQSk..."]
}
可能需要这样组织数据:
const payload = { data: [base64String] }
axios.post('/api/predict', payload)
具体要看后端接受什么格式。
成功响应一般包含 base64 编码的图片:
{
"data": ["data:image/png;base64,iVBORw..."]
}
前端可以直接赋值给 <img :src="result"> 显示。
添加完善的错误捕获机制:
try {
const res = await axios.post('/api/predict', payload)
if (res.data && res.data.data) {
this.result = res.data.data[0]
} else {
throw new Error('无效响应')
}
} catch (err) {
if (err.response?.status === 500) {
alert('后端处理出错')
} else if (err.code === 'ECONNREFUSED') {
alert('请先启动后端服务')
} else {
alert('未知错误:' + err.message)
}
}
<template>
<div class="container">
<h2>人像卡通化</h2>
<input type="file" @change="handleFile" accept="image/*" />
<button @click="convert" :disabled="!image">开始转换</button>
<div v-if="loading">处理中...</div>
<img v-if="result" :src="result" alt="卡通化结果" />
<a v-if="result" :href="result" download="cartoon.png">下载结果</a>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
image: null,
result: null,
loading: false
}
},
methods: {
handleFile(e) {
const file = e.target.files[0]
const reader = new FileReader()
reader.onload = () => {
this.image = reader.result
}
reader.readAsDataURL(file)
},
async convert() {
if (!this.image) return
this.loading = true
try {
const response = await axios.post('/api/predict', { data: [this.image] })
if (response.data?.data?.[0]) {
this.result = response.data.data[0]
} else {
alert('转换失败:无返回数据')
}
} catch (error) {
console.error(error)
alert('调用失败,请检查后端是否运行')
} finally {
this.loading = false
}
}
}
}
</script>
<style>
.container { padding: 20px; }
img { max-width: 100%; margin-top: 20px; }
</style>
本文详细讲解了如何让 Vue 前端成功对接 UNet 人像卡通化后端服务,重点解决了跨域问题。
介绍了三种实用方案:
只要后端服务正常运行,前端正确发送请求,就能轻松实现'上传照片 → 卡通化 → 展示结果'的完整流程。下一步可继续优化体验,比如增加进度条、支持拖拽上传等。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online