From 9d7f4acaf1792554215624f13678e58486220eee Mon Sep 17 00:00:00 2001 From: DarkSky <25152247+darkskygit@users.noreply.github.com> Date: Sun, 15 Feb 2026 19:16:36 +0800 Subject: [PATCH] fix: s3 upload compatibility (#14445) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #14432 #### PR Dependency Tree * **PR #14445** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) ## Summary by CodeRabbit * **Refactor** * Improved file upload handling to ensure consistent support for different data formats during object and multipart uploads. * Enhanced type safety throughout storage and workflow components by removing unnecessary type assertions. --- .../server/src/base/storage/providers/r2.ts | 15 +++++++++++++-- .../server/src/base/storage/providers/s3.ts | 2 +- .../server/src/plugins/copilot/controller.ts | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/backend/server/src/base/storage/providers/r2.ts b/packages/backend/server/src/base/storage/providers/r2.ts index b7f08d0d4..71d511e46 100644 --- a/packages/backend/server/src/base/storage/providers/r2.ts +++ b/packages/backend/server/src/base/storage/providers/r2.ts @@ -175,7 +175,7 @@ export class R2StorageProvider extends S3StorageProvider { body: Readable | Buffer | Uint8Array | string, options: { contentType?: string; contentLength?: number } = {} ) { - return this.client.putObject(key, body as any, { + return this.client.putObject(key, this.normalizeBody(body), { contentType: options.contentType, contentLength: options.contentLength, }); @@ -192,13 +192,24 @@ export class R2StorageProvider extends S3StorageProvider { key, uploadId, partNumber, - body as any, + this.normalizeBody(body), { contentLength: options.contentLength } ); return result.etag; } + private normalizeBody(body: Readable | Buffer | Uint8Array | string) { + // s3mini does not accept Node.js Readable directly. + // Convert it to Web ReadableStream for compatibility. + if (body instanceof Readable) { + return Readable.toWeb(body); + } else if (typeof body === 'string') { + return this.encoder.encode(body); + } + return body; + } + override async get( key: string, signedUrl?: boolean diff --git a/packages/backend/server/src/base/storage/providers/s3.ts b/packages/backend/server/src/base/storage/providers/s3.ts index 1bafcb395..0759dbc5d 100644 --- a/packages/backend/server/src/base/storage/providers/s3.ts +++ b/packages/backend/server/src/base/storage/providers/s3.ts @@ -281,7 +281,7 @@ export class S3StorageProvider implements StorageProvider { this.logger.verbose(`Read object \`${key}\``); return { - body: Readable.fromWeb(obj.body as any), + body: Readable.fromWeb(obj.body), metadata: { contentType: contentType ?? 'application/octet-stream', contentLength: contentLength ?? 0, diff --git a/packages/backend/server/src/plugins/copilot/controller.ts b/packages/backend/server/src/plugins/copilot/controller.ts index 88e931389..a9885c8f3 100644 --- a/packages/backend/server/src/plugins/copilot/controller.ts +++ b/packages/backend/server/src/plugins/copilot/controller.ts @@ -560,7 +560,7 @@ export class CopilotController implements BeforeApplicationShutdown { status: data.status, id: data.node.id, type: data.node.config.nodeType, - } as any, + }, }; } })