
本文作者:茉卷,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 的基本调用格式如下:
json
{
"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 的混合方案
markdown
# 文生图应用技术方案
## 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 核心功能模块
1. **用户界面模块**
- 文本输入框
- 参数配置面板
- 图像预览区域
- 历史记录管理
2. **API 调用模块**
- 请求封装
- 流式响应处理
- 错误处理和重试
- 认证管理
3. **图像管理模块**
- 图像下载和缓存
- 格式转换
- 批量处理
- 存储管理
4. **用户体验模块**
- 进度显示
- 实时预览
- 响应式设计
- 移动端适配
## 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 核心组件设计
```typescript
// 主要组件结构
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 核心服务
```typescript
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 数据库设计
```sql
-- 生成任务表
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 流式响应处理
```javascript
// 前端 SSE 处理
const eventSource = new EventSource('/api/stream/' + taskId);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'progress') {
updateProgress(data.progress);
} else if (data.type === 'image') {
addImage(data.image);
}
};
```
#### 5.3.2 图像缓存策略
- 本地缓存:浏览器 IndexedDB
- 服务端缓存:Redis + 文件系统
- CDN 缓存:云存储 + CDN 加速
#### 5.3.3 错误处理
- API 限流处理
- 网络超时重试
- 图像下载失败恢复
- 用户友好的错误提示
## 6. 部署方案
### 6.1 开发环境
```bash
# 前端开发
npm run dev
# 后端开发
npm run dev:server
# 数据库
docker run -d postgres:14
```
### 6.2 生产环境
```yaml
# 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 开发建议
1. **MVP 优先** :先实现核心功能,再逐步完善
2. **用户体验** :重视加载状态和错误处理
3. **性能监控** :及早建立监控体系
4. **安全第一** :API Key 和用户数据安全
5. **可扩展性** :考虑未来功能扩展需求
### 11.3 风险评估
- **API 限制** :注意调用频率和成本控制
- **图像存储** :考虑存储成本和清理策略
- **用户增长** :准备扩容方案
- **合规要求** :注意内容审核和版权问题
这个方案提供了完整的技术路线图,可以根据实际需求和资源情况选择合适的实现方案。

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

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

2.4 使用对象存储上传图片、获取 URL
我可以使用火山引擎 【对象存储】 Node.js SDK 来保存图片、获取图片 URL ,但是怎么实现呢?
注意⚠️,火山引擎云服务需要配置 AK,具体参考 www.volcengine.com/docs/6291/6... (这部分大家按照文档配置即可)
安装 Node.js SDK
bash
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_ACCESS_KEY
echo $TOS_SECRET_KEY
如果配置成功,则返回如下示例:
AKTPYmI1Z****
T1dJM01UU****
初始化客户端: 创建 TOS 客户端实例,配置必要的区域和端点信息:
perl
创建 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 接口实现文件上传功能:
javascript
您可以通过以下示例代码,使用 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);
} else if (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 参数处理上传进度,代码示例如下。
javascript
// 导入 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);
} else if (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');
} else if (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} %`);
} else if (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} %`);
} else if (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 机制获取临时访问链接。

javascript
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 项目。按照官方文档的推荐方式进行初始化,参考 vite.dev/guide/。
bash
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
具体怎么实现?- 具体实现方法见问题链中的步骤
提示词(因为只是个例子,我们简单一点)
vbnet
我想做一个换装、多图融合应用。
我可以用 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 $ARK_API_KEY" \
-d '{
"model": "doubao-Seedream-4-0-250828",
"prompt": "星际穿越,黑洞,黑洞里冲出一辆快支离破碎的复古列车,抢视觉冲击力,电影大片,末日既视感,动感,对比色,oc渲染,光线追踪,动态模糊,景深,超现实主义,深蓝,画面通过细腻的丰富的色彩层次塑造主体与场景,质感真实,暗黑风背景的光影效果营造出氛围,整体兼具艺术幻想感,夸张的广角透视效果,耀光,反射,极致的光影,强引力,吞噬",
"size": "2K",
"sequential_image_generation": "disabled",
"stream": false,
"response_format": "url",
"watermark": true
}'
我需要先把图片上传到云端(火山引擎对象存储),然后获得图片的URL链接
我可以使用火山引擎 【对象存储】Node.js SDK 来保存图片、获取图片URL
具体实现方法:
安装 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_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);
} else if (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来设计服务,模块需要设计成可复用的。
规则:
不要使用 @import url(' 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 如下:
less
[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 如下。
vbnet
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 如何填写右边这些参数,并完成填写。
css
Allow-Headers:*
Expose-Headers:
ETag
Content-Length
Content-Type
Last-Modified
Accept-Ranges
Cache-Control
修改 CORS 规则后,继续运行。

关键错误如下。
css
{"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 方法,看意思,还需要列举桶的权限。

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

修改桶权限后,继续运行。然而又出错了:Authorization 头域中的签名算法采用了 TOS 不支持的算法。
css
{
"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 输入错误,复制的时候少了几个字符。
php
// 上传文件
await this.tosClient.putObject({
bucket: config.tosConfig.bucketName,
key: objectKey,
body: file,
contentType: file.type
});
重新配置后,上传图片成功。
另外一个问题:多图融合生成出错。
csharp
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 分析,给出解决办法,设置代理。
markdown
## 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 自动检查结果
通过结合多图融合功能和豆包视觉模型,可以实现自动化的结果检查机制。系统可以自动分析生成的图像,识别潜在的质量问题,并为用户提供改进建议。

