本文作者:茉卷,TRAE 开发者用户
本文是一篇实战过程分享,详细介绍了如何在 TRAE IDE 中开发一个多图融合应用程序,包括如何初始化项目、基于问题链设计核心的 AI 提示词,以及前后端的关键代码实现。
项目背景与需求分析
1.1 项目触发点
核心需求:开发一个换装、多图融合应用,通过 AI 技术实现图像的智能合成与处理。
技术路线:
- 前端:Vite + React 18 + TypeScript
- 后端:FastAPI (Python)
- AI 服务:Seedream 4.0 API
- 存储:火山引擎对象存储
1.2 API 接入
基于豆包 Seedream 4.0 API 的核心能力,我们可以实现多种图像生成模式。API 的基本调用格式如下:
{
"model": "doubao-Seedream-4-0-250828",
"prompt": "用户输入的文本描述",
"image": ["图片URL1", "图片URL2"],
"sequential_image_generation": "auto",
"sequential_image_generation_options": {
"max_images": 3
},
"response_format": "url",
"size": "2K",
"stream": true,
"watermark": true
}
1.3 技术架构设计
整体架构流程设计:
用户上传图片 → 火山引擎对象存储 → 获取图片URL → Seedream API → 生成融合图片
核心技术栈选择:
- 方案一: React 18 + TypeScript + Node.js + Express
- 方案二: Vue.js 3 + TypeScript + FastAPI (Python) ✅
- 方案三: React Native/Flutter (移动端)
最终选择:前端 React + 后端 FastAPI 的混合方案
上下滑动查看完整内容
# 文生图应用技术方案
## 1. 项目概述
基于豆包 Seedream API 开发的文生图应用,支持用户输入文本描述生成高质量图像。应用支持多种图像尺寸、批量生成、流式响应等功能。
## 2. API 分析
### 2.1 豆包 Seedream API 特性
- **模型**: `doubao-Seedream-4-0-250828`
- **认证**: Bearer Token 认证
- **响应格式**: 支持 URL 和 base64 格式
- **图像尺寸**: 支持多种尺寸(包括 2K)
- **批量生成**: 支持连续图像生成,最多 3 张
- **流式响应**: 支持实时流式返回
- **水印**: 可选择是否添加水印
### 2.2 API 参数详解
```json
{
"model": "doubao-Seedream-4-0-250828",
"prompt": "文本描述",
"image": ["", ""], // 参考图像(可选)
"sequential_image_generation": "auto", // 连续生成模式
"sequential_image_generation_options": {
"max_images": 3 // 最大生成数量
},
"response_format": "url", // 返回格式
"size": "2K", // 图像尺寸
"stream": true, // 流式响应
"watermark": true // 是否添加水印
}
3. 技术架构方案
3.1 整体架构
前端界面 ↔ 后端API服务 ↔ 豆包API ↔ 文件存储
↓ ↓
用户交互 业务逻辑处理
3.2 核心功能模块
- 用户界面模块
- 文本输入框
- 参数配置面板
- 图像预览区域
- 历史记录管理
- API 调用模块
- 请求封装
- 流式响应处理
- 错误处理和重试
- 认证管理
- 图像管理模块
- 图像下载和缓存
- 格式转换
- 批量处理
- 存储管理
- 用户体验模块
- 进度显示
- 实时预览
- 响应式设计
- 移动端适配
4. 推荐技术栈
4.1 方案一:现代 Web 应用(推荐)
前端技术栈:
- 框架: React 18 + TypeScript
- UI 库: Ant Design 或 Material-UI
- 状态管理: Zustand 或 Redux Toolkit
- HTTP 客户端: Axios
- 构建工具: Vite
- 样式: Tailwind CSS
后端技术栈: - 框架: Node.js + Express 或 Fastify
- 语言: TypeScript
- 数据库: PostgreSQL + Prisma ORM
- 文件存储: 本地存储 + 云存储(可选)
- 缓存: Redis
- 部署: Docker + PM2
优势: - 开发效率高,生态丰富
- 前后端技术栈统一
- 社区支持好,学习成本低
- 适合快速迭代
4.2 方案二:Python 全栈
前端技术栈:
- 框架: Vue.js 3 + TypeScript
- UI 库: Element Plus
- 状态管理: Pinia
- 构建工具: Vite
后端技术栈: - 框架: FastAPI
- 数据库: SQLite/PostgreSQL + SQLAlchemy
- 异步处理: asyncio
- 文件处理: Pillow
- 部署: Uvicorn + Gunicorn
优势: - Python 生态丰富,AI 相关库多
- FastAPI 性能优秀,文档自动生成
- 适合数据处理和 AI 集成
4.3 方案三:移动端 APP
技术栈:
- 框架: React Native 或 Flutter
- 状态管理: Redux/Provider
- 网络: Axios/Dio
- 图像处理: 原生库
优势: - 原生体验好
- 离线功能支持
- 推送通知
- 相机集成
5. 详细实现方案
5.1 前端实现要点
5.1.1 核心组件设计
// 主要组件结构
interface AppState {
prompt: string;
images: GeneratedImage[];
loading: boolean;
config: GenerationConfig;
}
interface GenerationConfig {
size: string;
maxImages: number;
watermark: boolean;
stream: boolean;
}
5.1.2 流式响应处理
- 使用 Server-Sent Events(SSE) 或 WebSocket
- 实时显示生成进度
- 支持取消操作
- 错误恢复机制
5.1.3 用户体验优化
- 响应式布局设计
- 图像懒加载
- 无限滚动历史记录
- 拖拽上传参考图像
- 快捷键支持
5.2 后端实现要点
5.2.1 API 设计
POST /api/generate - 生成图像
GET /api/images/:id - 获取图像
GET /api/history - 获取历史记录
DELETE /api/images/:id - 删除图像
GET /api/stream/:taskId - 流式响应
5.2.2 核心服务
class ImageGenerationService {
async generateImage(prompt: string, config: Config): Promise<Task>
async getTaskStatus(taskId: string): Promise<TaskStatus>
async downloadImage(url: string): Promise<Buffer>
async saveImage(buffer: Buffer): Promise<string>
}
5.2.3 数据库设计
-- 生成任务表
CREATE TABLE generation_tasks(
id UUID PRIMARY KEY,
prompt TEXT NOT NULL,
config JSONB,
status VARCHAR(20),
created_at TIMESTAMP,
completed_at TIMESTAMP
);
-- 生成图像表
CREATE TABLE generated_images(
id UUID PRIMARY KEY,
task_id UUID REFERENCES generation_tasks(id),
url TEXT,
local_path TEXT,
size VARCHAR(10),
created_at TIMESTAMP
);
5.3 关键技术实现
5.3.1 流式响应处理
// 前端 SSE 处理
const eventSource = new EventSource('/api/stream/' + taskId);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'progress') {
updateProgress(data.progress);
} elseif (data.type === 'image') {
addImage(data.image);
}
};
5.3.2 图像缓存策略
- 本地缓存:浏览器 IndexedDB
- 服务端缓存:Redis + 文件系统
- CDN 缓存:云存储 + CDN 加速
5.3.3 错误处理
- API 限流处理
- 网络超时重试
- 图像下载失败恢复
- 用户友好的错误提示
6. 部署方案
6.1 开发环境
# 前端开发
npm run dev
# 后端开发
npm run dev:server
# 数据库
docker run -d postgres:14
6.2 生产环境
# docker-compose.yml
version: '3.8'
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
backend:
build: ./backend
ports:
- "8000:8000"
environment:
- ARK_API_KEY=${ARK_API_KEY}
database:
image: postgres:14
environment:
- POSTGRES_DB=texttoimage
redis:
image: redis:7-alpine
6.3 云部署选项
- Vercel + Railway: 适合小型项目
- AWS/阿里云: 适合企业级应用
- Docker + Kubernetes: 适合大规模部署
7. 性能优化
7.1 前端优化
- 代码分割和懒加载
- 图像压缩和格式优化
- 虚拟滚动长列表
- Service Worker 缓存
7.2 后端优化
- API 响应缓存
- 数据库查询优化
- 图像 CDN 加速
- 负载均衡
7.3 用户体验优化
- 骨架屏加载
- 预加载关键资源
- 离线功能支持
- 渐进式 Web 应用 (PWA)
8. 安全考虑
8.1 API 安全
- API Key 安全存储
- 请求频率限制
- 输入内容过滤
- HTTPS 强制使用
8.2 数据安全
- 用户数据加密
- 图像访问权限控制
- 定期数据清理
- 备份策略
9. 监控和维护
9.1 监控指标
- API 调用成功率
- 图像生成时间
- 用户活跃度
- 错误率统计
9.2 日志管理
- 结构化日志
- 错误追踪
- 性能监控
- 用户行为分析
10. 项目时间规划
第一阶段(1-2周):基础功能
- 基本 UI 界面
- API 调用封装
- 图像生成和显示
第二阶段(2-3周):功能完善
- 流式响应
- 历史记录
- 参数配置
- 错误处理
第三阶段(1-2周):优化和部署
- 性能优化
- 用户体验改进
- 部署上线
- 测试和修复
11. 总结和建议
11.1 推荐方案
优先推荐方案一(React + Node.js),理由:
- 技术栈成熟稳定
- 开发效率高
- 社区支持好
- 适合快速原型和迭代
11.2 开发建议
- MVP 优先:先实现核心功能,再逐步完善
- 用户体验:重视加载状态和错误处理
- 性能监控:及早建立监控体系
- 安全第一:API Key 和用户数据安全
- 可扩展性:考虑未来功能扩展需求
11.3 风险评估
- API 限制:注意调用频率和成本控制
- 图像存储:考虑存储成本和清理策略
- 用户增长:准备扩容方案
- 合规要求:注意内容审核和版权问题
这个方案提供了完整的技术路线图,可以根据实际需求和资源情况选择合适的实现方案。

**方案关键技术难点分析**
我打算使用的方案
方案1 的前端:vite +React 18 + TypeScript
方案2 的后端: FastApi (python)
基于API 文档内容,给出 关键参数,比如 调用API 必须使用哪些参数,我可以从哪里获取? 整理出来,给出建议,不要修改代码:
**2.1 AI 回复关键内容(找到问题)**
model:固定,不重要
prompt: 我自己输入,不重要
ARK\_API\_KEY (认证令牌): 注册就能有,不重要
......
**Image: API 不能直接上传图片,需要传递图片 URL**
**上下滑动查看完整内容**
🔑 API 关键参数分析
必需参数
- model : "doubao-Seedream-4-0-250828" (固定值)
- prompt : 用户输入的文本描述 (字符串)
- Authorization Header : Bearer $ARK_API_KEY (认证令牌)
重要可选参数
-
response_format : "url" 或 "base64" (推荐使用 url)
-
size : 图像尺寸,如 "2K" 、 "1024x1024" 等
-
stream : true/false (是否启用流式响应)
-
watermark : true/false (是否添加水印)
-
sequential_image_generation : "auto" (连续生成模式)
-
sequential_image_generation_options : {"max_images": 3} (最大生成数量)
-
image: 图像 URL 直接提供图像的网络链接
......
**2.2 图片上传与 URL 获取**
在实现过程中,我遇到一个问题:图片如何上传到服务器,如何获得上传服务器的图片链接?

通过问询 TRAE 得到方案,我们选择一个我们熟悉的。这里我选择云存储(火山引擎)。
核心解决方案
1. 技术架构设计
- 前端上传流程 :用户选择图片 → 预览展示 → FormData封装 → 上传到FastAPI
- 后端处理流程 :接收文件 → 验证格式 → 生成唯一文件名 → 保存到本地/云存储 → 返回访问链接
- 链接获取方式 :通过FastAPI静态文件服务或云存储CDN提供公开访问链接
2. FastAPI后端实现要点
- 文件上传接口 :使用 UploadFile 类型处理多文件上传
- 存储策略 :本地存储 + 可选云存储(阿里云OSS/腾讯云COS)
- 链接生成 :自动生成带域名的完整访问URL
- 文件管理 :支持文件列表查询、删除等操作
3. React前端实现要点
- 上传组件 :支持拖拽上传、多文件选择、进度显示
- 预览功能 :实时预览选中的图片
- 状态管理 :使用useState管理上传状态和文件列表
- 错误处理 :完善的错误提示和重试机制
**2.3 火山引擎对象存储集成**
我需要先把图片上传到云端(火山引擎对象存储),然后获得图片的 URL 链接。因此我要调查火山引擎的对象存储。
文档链接:
https://www.volcengine.com/docs/6349/113481
问问 TRAE


我比较熟悉 Node.js 所以选择 Node.js SDK

**2.4 使用对象存储上传图片、获取 URL**
我可以使用火山引擎 【对象存储】 Node.js SDK 来保存图片、获取图片 URL ,但是怎么实现呢?
注意⚠️,火山引擎云服务需要配置 AK,具体参考 https://www.volcengine.com/docs/6291/65568 (这部分大家按照文档配置即可)
**安装 Node.js SDK**
npm init
npm i @volcengine/tos-sdk
打开终端并执行以下命令打开文件。
nano ~/.bash_profile
在文件末尾添加 AKSK 信息。
export TOS_ACCESS_KEY=AKTPYmI1Z****
export TOS_SECRET_KEY=T1dJM01UU****
保存文件并退出。
执行以下命令生效配置信息。
source ~/.bash_profile
执行以下命令验证配置信息。
echo TOS_SECRET_KEY
如果配置成功,则返回如下示例:
AKTPYmI1Z****
T1dJM01UU****
**初始化客户端:** 创建 TOS 客户端实例,配置必要的区域和端点信息:
创建 TosClient
使用必选参数初始化
以下代码展示如何使用 TOS 域名等必选参数初始化 TosClient,包括 AccessKey ID、AccessKey Secret、Endpoint 和 Region。
说明
TOS 支持的 Region 及 Endpoint 信息,请参见地域及访问域名。
AKSK 信息可从环境变量获取,配置方式,请参见配置访问凭证。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入import { TosClient } from '@volcengine/tos-sdk';
// 创建客户端const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。endpoint: "Provide your endpoint", // 填写域名地址
});
**文件上传实现:** 使用 **putObjectFromFile** 接口实现文件上传功能:
**上下滑动查看完整内容**
您可以通过以下示例代码,使用 putObjectFromFile 接口,通过指定文件路径将文件上传到 TOS 指定 example_dir目录下的 example.txt 文件。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入import { TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
import fs from 'fs';
// 创建客户端const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error){
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} elseif (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main(){
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/example.txt';
// 直接使用文件路径上传文件await client.putObjectFromFile({
bucket: bucketName,
key: objectName,
filePath: './example.txt',
});
// 查询刚刚上传对象的大小const { data } = await client.headObject({
bucket: bucketName,
key: objectName,
});
console.log('object size:', data['content-length']);
} catch (error) {
handleError(error);
}
}
main();
**配置进度条:** 上传时可通过 **dataTransferStatusChange** 参数处理上传进度,代码示例如下。
**上下滑动查看完整内容**
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入import { DataTransferType, TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
// 创建客户端const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error){
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} elseif (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main(){
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/example.txt';
// 上传对象await client.putObject({
bucket: bucketName,
key: objectName,
// 将字符串 "Hello TOS" 上传到指定 example_dir 目录下的 example.txtbody: Buffer.from('Hello TOS'),
// 通过自定义方式设置回调函数查看上传进度dataTransferStatusChange: (event) => {
if (event.type === DataTransferType.Started) {
console.log('Data Transfer Started');
} elseif (event.type === DataTransferType.Rw) {
const percent = ((event.consumedBytes / event.totalBytes) * 100).toFixed(2);
console.log(Once Read:${event.rwOnceBytes},ConsumerBytes/TotalBytes: ${event.consumedBytes}/${event.totalBytes},${percent}%);
} elseif (event.type === DataTransferType.Succeed) {
const percent = ((event.consumedBytes / event.totalBytes) * 100).toFixed(2);
console.log(Data Transfer Succeed, ConsumerBytes/TotalBytes:${event.consumedBytes}/${event.totalBytes},${percent}%);
} elseif (event.type === DataTransferType.Failed) {
console.log('Data Transfer Failed');
}
},
});
// 查询刚刚上传的对象const { data } = await client.headObject({
bucket: bucketName,
key: objectName,
});
console.log('object size:', data['content-length']);
} catch (error) {
handleError(error);
}
}
main();
**URL 获取方法:** 通过预签名 URL 机制获取临时访问链接。

**上下滑动查看完整内容**
const { TosClient } = require('@volcengine/tos-sdk');
const client = new TosClient({
accessKeyId: 'yourAccessKey',
accessKeySecret: 'yourSecretKey',
region: 'yourRegion',
endpoint: 'yourEndpoint'
});
async function getTempUrl(){
try {
const result = await client.getPreSignedUrl({
bucket: 'yourBucketName',
key: 'yourObjectKey',
expires: 3600// URL有效期,单位秒,默认1800秒
});
console.log('临时访问URL:', result.signedUrl);
} catch (error) {
console.error('获取临时URL失败:', error);
}
}
getTempUrl();
至此,问题链结束。
| | |
| --- | --- |
|
\_
|
我想做一个换装、多图融合应用。
|
| | |
| --- | --- |
|
☑️
|
我应该如何做?
|
| | |
| --- | --- |
|
\_
|
我可以用 API 来实现
|
| | |
| --- | --- |
|
☑️
|
API 如何具体实现?
|
| | |
| --- | --- |
|
\_
|
方案 1 的前端:vite +React 18 + TypeScript
|
| | |
| --- | --- |
|
\_
|
方案 2 的后端: FastApi (python)
|
| | |
| --- | --- |
|
☑️
|
实现上面方案的关键点有哪些?
|
| | |
| --- | --- |
|
☑️
|
我遇到了一个问题:图片如何上传到服务器,如何获得上传服务器的图片链接?
|
| | |
| --- | --- |
|
\_
|
我需要先把图片上传到云端(火山引擎对象存储),然后获得图片的 URL 链接
|
| | |
| --- | --- |
|
☑️
|
我应该如何实现图片上传?
|
| | |
| --- | --- |
|
\_
|
我可以使用火山引擎 【对象存储】Node.js SDK 来保存图片、获取图片 URL
|
| | |
| --- | --- |
|
☑️
|
具体怎么实现?
|
| | |
| --- | --- |
|
\_
|
具体实现方法见上面 步骤
|

**实战步骤**
**3.1 创建项目初始环境**
基于我们确定的技术方案,使用 Vite 创建 React 18 + TypeScript 项目。按照官方文档的推荐方式进行初始化,参考 https://vite.dev/guide/。
npm create vite@latest
cd tryout_pro
ls -l
npm install
npm run dev
项目创建完成后,我们得到了一个标准的 Vite + React 18 + TypeScript 开发环境,为后续的功能开发奠定了基础。

打开 TRAE,进入项目目录


**3.2 核心提示词设计**
**基于问题链生成的完整提示词**
为了确保 AI 辅助开发的效果,我们设计了完整的提示词体系。这个提示词不仅包含了技术需求,还涵盖了设计规范和最佳实践:
| | |
| --- | --- |
|
\_
|
我想做一个换装、多图融合应用。
|
| | |
| --- | --- |
|
☑️
|
我应该如何做?
|
| | |
| --- | --- |
|
\_
|
我可以用 API 来实现
|
| | |
| --- | --- |
|
☑️
|
API 如何具体实现?
|
| | |
| --- | --- |
|
\_
|
方案1 的前端:vite +React 18 + TypeScript
|
| | |
| --- | --- |
|
\_
|
方案2 的后端: FastApi (python)
|
| | |
| --- | --- |
|
☑️
|
实现上面方案的关键点有哪些?
|
| | |
| --- | --- |
|
☑️
|
我遇到了一个问题:图片如何上传到服务器,如何获得上传服务器的图片链接?
|
| | |
| --- | --- |
|
\_
|
我需要先把图片上传到云端(火山引擎对象存储),然后获得图片的URL链接
|
| | |
| --- | --- |
|
☑️
|
我应该如何实现图片上传?
|
| | |
| --- | --- |
|
\_
|
我可以使用火山引擎 【对象存储】Node.js SDK 来保存图片、获取图片URL
|
| | |
| --- | --- |
|
☑️
|
具体怎么实现?
|
| | |
| --- | --- |
|
\_
|
具体实现方法见问题链中的步骤
|
提示词(因为只是个例子,我们简单一点)
**上下滑动查看完整内容**
我想做一个换装、多图融合应用。
我可以用 API来实现,
使用 vite +React 18 + TypeScript 方案
需要使用的图片融合API:图片生成 API(Seedream 4.0 API)
文档:https://www.volcengine.com/docs/82379/1541523
不同模型支持的图片生成能力简介
doubao-Seedream-4.0new
生成组图(组图:基于您输入的内容,生成的一组内容关联的图片;需配置sequential_image_generation为auto)
多图生组图,根据您输入的 多张参考图片(2-10)+文本提示词 生成一组内容关联的图片(输入的参考图数量+最终生成的图片数量≤15张)。
单图生组图,根据您输入的 单张参考图片+文本提示词 生成一组内容关联的图片(最多生成14张图片)。
文生组图,根据您输入的 文本提示词 生成一组内容关联的图片(最多生成15张图片)。
生成单图(配置sequential_image_generation为disabled)
多图生图,根据您输入的 多张参考图片(2-10)+文本提示词 生成单张图片。
单图生图,根据您输入的 单张参考图片+文本提示词 生成单张图片。
文生图,根据您输入的 文本提示词 生成单张图片。
输入示例:curl -X POST https://ark.cn-beijing.volces.com/api/v3/images/generations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TOS_ACCESS_KEY
echo $TOS_SECRET_KEY
如果配置成功,则返回如下示例:
AKTPYmI1Z****
T1dJM01UU****
您可以通过以下示例代码,使用 putObjectFromFile 接口,通过指定文件路径将文件上传到 TOS 指定 example_dir目录下的 example.txt 文件。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入import { TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
import fs from 'fs';
// 创建客户端const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error){
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} elseif (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main(){
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/example.txt';
// 直接使用文件路径上传文件await client.putObjectFromFile({
bucket: bucketName,
key: objectName,
filePath: './example.txt',
});
// 查询刚刚上传对象的大小const { data } = await client.headObject({
bucket: bucketName,
key: objectName,
});
console.log('object size:', data['content-length']);
} catch (error) {
handleError(error);
}
}
main();
获取上传文件URL:
const { TosClient } = require('@volcengine/tos-sdk');
const client = new TosClient({
accessKeyId: 'yourAccessKey',
accessKeySecret: 'yourSecretKey',
region: 'yourRegion',
endpoint: 'yourEndpoint'
});
async function getTempUrl(){
try {
const result = await client.getPreSignedUrl({
bucket: 'yourBucketName',
key: 'yourObjectKey',
expires: 3600// URL有效期,单位秒,默认1800秒
});
console.log('临时访问URL:', result.signedUrl);
} catch (error) {
console.error('获取临时URL失败:', error);
}
}
getTempUrl();
你需要生成一个UI界面,用户可以输入几张图片,提示词,然后你调用接口,生成一些或者一张图片。
图片生成时,你应该先调用文件上传接口,把用户的图片上传到火山引擎对象存储,然后再获得上传图片的URL链接,然后再调用Seedream4 接口生成融合后的图片。
你的设计需要符合业界最佳实践,使用OPENAI 黑白灰的风格,采用互动式界面响应编程。你需要在代码中增加必要的LOG 用来调试关键步骤。你需要生成一个配置页面,用来让用户配置整个代码中的关键参数,比如 AK SK 等等。你需要使用hook来设计服务,模块需要设计成可复用的。
规则:
不要使用 @importurl(' https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap ');这种远程的css
给出你的国际一流设计和代码(先生成设计文档,再进行编码):
**3.3 运行 TRAE MAX 模式**



修了一下 taiwind css 不正常显示的问题,第一版基本 OK。

**3.4 用户界面实现效果**
经过开发和调试,我们实现了一个功能完整的用户界面。

主页

提示词输入界面

模型选择面板

配置管理界面

配置导入导出
**关键参数全部列出** :TOS 的相关参数配置,需先参考火山引擎官方文档,再在其控制台完成配置,具体操作此处不做赘述。
**3.5 运行调试**
填入关键参数,开始调试。

首先遇到上传图片失败。
点击上传参考图片出错,打开浏览器控制台,可以看到错误: 对象存储客户端初始化问题。
我们之前让 AI 生成代码时,加上关键 LOG,这个非常重要。

具体出错 LOG 如下:
[2025-09-15T23:58:13.154Z] [INFO] Configuration updated successfully
loggingService.ts:111 [2025-09-15T23:58:13.155Z] [INFO] Configuration validation passed
loggingService.ts:111 [2025-09-15T23:58:13.155Z] [INFO] User action: Config updated
loggingService.ts:111 [2025-09-15T23:58:13.174Z] [INFO] Configuration validation passed
loggingService.ts:111 [2025-09-15T23:59:42.474Z] [INFO] User action: Batch upload started Object
loggingService.ts:111 [2025-09-15T23:59:42.475Z] [INFO] Uploading file 1/1: model.jpg
loggingService.ts:117 [2025-09-15T23:59:42.496Z] [ERROR] Failed to upload file 1: TOS客户端未初始化,请检查配置
outputToConsole @ loggingService.ts:117
loggingService.ts:111 [2025-09-15T23:59:42.496Z] [INFO] Timer Upload 1 files: 21.60ms
loggingService.ts:111 [2025-09-15T23:59:42.496Z] [INFO] Batch upload completed: 0/1 successful
loggingService.ts:111 [2025-09-15T23:59:42.496Z] [INFO] User action: Batch upload completed Object
2loggingService.ts:111 [2025-09-16T00:00:33.917Z] [INFO] Configuration validation passed
2loggingService.ts:111 [2025-09-16T00:00:33.923Z] [INFO] Configuration validation passed
我们让 AI 分析解决,这时退出 MAX 模式运行: AI 找到代码问题,修改。

修改后,再次上传,继续出错: **跨域访问被阻止。**

通过问豆包,发现因为 CORS policy,远端文件存储服务器不让 http://localhost:5173 访问。

关键 LOG 如下。
Access to XMLHttpRequest at 'https://my-tos-bucket.tos-cn-beijing.volces.com/images%2F1757981300662_bji0249wu7.png' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
通过问火山助手,得到需要配置一下跨域访问设置。


问问 TRAE 如何填写右边这些参数,并完成填写。


Allow-Headers:*
Expose-Headers:
ETag
Content-Length
Content-Type
Last-Modified
Accept-Ranges
Cache-Control
修改 CORS 规则后,继续运行。

关键错误如下。
{"Code":"NoSuchKey","RequestId":"24b301c8bc1b3d1468c8bc1b-ba9c638-1uyKPz-GO-cb-tos-1az-front-aza-1","HostId":"btUSQDgiIknwrpTcBAAQekBHZNDIrktk","Message":"The specified key does not exist.","EC":"0017-00000003","Key":"images/1757984846003_3s0aowh5umv.png"}
找到火山引擎对应错误说明。用户发起列举所有桶的请求,虽然 IAM 策略检查通过,但桶所属 Project 策略全部拒绝,导致请求被拒绝。
应用里只是调用了 ObjectPut 方法,看意思,还需要列举桶的权限。

在火山引擎中增加列举权限。(具体权限配置需要参考火山引擎文档,这里不做详细介绍,小伙伴们看 https://www.volcengine.com/docs/6349/74836)

修改桶权限后,继续运行。然而又出错了:Authorization 头域中的签名算法采用了 TOS 不支持的算法。
{
"Code": "InvalidAccessKeyId",
"RequestId": "98ed01c8c351153e68c8c351-ba9c733-1uyKtl-PuO-cb-tos-1az-front-aza-1",
"HostId": "HBMROHtSrfGJaldaYQIytieTiOQMecjZ",
"Message": "The Access Key Id you provided does not exist in our records.",
"EC": "0002-00000020",
"AccessKeyId": "AKTP0UQU6XTAL2Zmb6Z1w86g4cIFgY7WNdAgjaan1jB5H7"
}
出错代码解释如下。


由于我们通过 SDK 调用,没有涉及签名,这个应该是 AK 输入的不对,我仔细检查了 AK,发现 AK 输入错误,复制的时候少了几个字符。
// 上传文件
await this.tosClient.putObject({
bucket: config.tosConfig.bucketName,
key: objectKey,
body: file,
contentType: file.type
});
重新配置后,上传图片成功。


另外一个问题:多图融合生成出错。
Access to fetch at 'https://ark.cn-beijing.volces.com/api/v3/images/generations' from origin 'http://localhost:5173' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.



收集 LOG 让 AI 分析,给出解决办法,设置代理。
CORS问题分析
根据你遇到的错误信息,问题的核心是 CORS(跨域资源共享)策略阻止 。让我解释一下为什么需要使用代理和fetch:
为什么会出现CORS错误?
1.1.
同源策略限制 :浏览器的同源策略阻止从 http://localhost:5173 直接访问 https://ark.cn-beijing.volces.com
2.2.
预检请求失败 :浏览器发送OPTIONS预检请求时,服务器返回的 Access-Control-Allow-Headers 不包含 authorization 头
3.3.
服务器CORS配置 :豆包API服务器没有配置允许来自本地开发环境的跨域请求
为什么需要代理?
代理的作用 :
- 将API请求从浏览器的跨域请求转换为服务器端的同域请求
- Vite开发服务器作为中间层,代理转发请求到 https://ark.cn-beijing.volces.com
- 避免浏览器的CORS限制,因为代理请求是服务器到服务器的通信


Seedream4 模型报错。

查看代码,这个错是因为代码中的模型是 :doubao-Seedream-4.0 ,而正确的应该是:doubao-Seedream-4-0-250828。因此在 TRAE 中做一个替换即可。

最终,修复所有问题,完成。



**功能扩展**
**4.1 效果验证**
为了提升应用的智能化水平,我们集成了 Doubao-1.6-think 模型来分析多图融合生成的结果。这个功能可以自动评估生成图像的质量,判断是否符合用户的预期要求,为用户提供更加智能的体验。

**4.2 自动检查结果**
通过结合多图融合功能和豆包视觉模型,可以实现自动化的结果检查机制。系统可以自动分析生成的图像,识别潜在的质量问题,并为用户提供改进建议。


**完整参考代码**
https://ai.gitcode.com/susirial/GitCode-SeeAI-01-007/blob/main/README.md

