Explorar el Código

refactor: enhance importExcelTags method to improve file buffer handling and support multipart file uploads

Dave hace 3 semanas
padre
commit
849f8fb9cb

+ 18 - 49
apps/box-mgnt-api/src/mgnt-backend/feature/video-media/video-media.controller.ts

@@ -286,67 +286,36 @@ export class VideoMediaController {
   })
   @Post('import/excel-tags')
   async importExcelTags(@Req() req: FastifyRequest, @Body() _body: any) {
-    const getBuffer = async (file: any): Promise<Buffer | undefined> => {
-      if (!file) return undefined;
-      if (Buffer.isBuffer(file)) return file;
-      if (file instanceof Uint8Array) return Buffer.from(file);
-
-      const candidate =
-        file.buffer ?? file.data ?? file.value ?? file._buf ?? undefined;
-      if (Buffer.isBuffer(candidate)) return candidate;
-      if (candidate instanceof Uint8Array) return Buffer.from(candidate);
-      if (typeof candidate === 'string') return Buffer.from(candidate);
-
-      if (typeof file.toBuffer === 'function') {
-        const buf = await file.toBuffer();
-        if (Buffer.isBuffer(buf)) return buf;
-      }
-
-      if (file.file) {
-        const chunks: Buffer[] = [];
-        for await (const chunk of file.file) {
-          chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
-        }
-        if (chunks.length > 0) {
-          return Buffer.concat(chunks);
-        }
-      }
-
-      return undefined;
-    };
-
     // fastify multipart
     const reqAny = req as any;
-    const bodyFile = reqAny.body?.file;
-    const mpFile: MultipartFile | undefined = Array.isArray(bodyFile)
+    const body = reqAny.body;
+    const bodyFile = body?.file ?? body?.files;
+    let mpFile: MultipartFile | undefined = Array.isArray(bodyFile)
       ? bodyFile[0]
       : bodyFile;
 
-    let buf = await getBuffer(mpFile);
-
-    if (!buf?.length && typeof reqAny.file === 'function') {
-      const part = await reqAny.file();
-      buf = await getBuffer(part);
+    if (!mpFile && body && typeof body === 'object') {
+      const values = Object.values(body).flatMap((value: any) =>
+        Array.isArray(value) ? value : [value],
+      );
+      mpFile = values.find(
+        (value: any) =>
+          value &&
+          (typeof value.toBuffer === 'function' ||
+            value.file ||
+            value.filename),
+      );
     }
 
-    if (!buf?.length && typeof reqAny.parts === 'function') {
-      for await (const part of reqAny.parts()) {
-        if (part?.type === 'file' && part?.fieldname === 'file') {
-          buf = await getBuffer(part);
-          if (buf?.length) break;
-        }
-      }
+    if (!mpFile && reqAny.isMultipart?.()) {
+      mpFile = await reqAny.file();
     }
 
-    if (!buf) {
+    if (!mpFile) {
       throw new BadRequestException('No file uploaded');
     }
 
-    if (!buf.length) {
-      throw new BadRequestException('Empty file');
-    }
-
-    return this.videoMediaService.importExcelTags(buf);
+    return this.videoMediaService.importExcelTags(mpFile);
   }
 
   /**

+ 49 - 3
apps/box-mgnt-api/src/mgnt-backend/feature/video-media/video-media.service.ts

@@ -301,10 +301,56 @@ export class VideoMediaService {
     return Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
   }
 
-  async importExcelTags(file: Buffer | Uint8Array) {
-    const buffer = Buffer.isBuffer(file) ? file : Buffer.from(file ?? []);
+  private async readUploadBuffer(file: MultipartFile): Promise<Buffer> {
+    const toBuffer = (value: unknown): Buffer | undefined => {
+      if (!value) return undefined;
+      if (Buffer.isBuffer(value)) return value;
+      if (value instanceof Uint8Array) return Buffer.from(value);
+      if (Array.isArray(value)) return Buffer.from(value);
+      if (typeof value === 'string') return Buffer.from(value, 'binary');
+      if (typeof value === 'object') {
+        try {
+          return Buffer.from(value as ArrayLike<number>);
+        } catch {
+          return undefined;
+        }
+      }
+      return undefined;
+    };
+
+    const source = (file as any)?.file as NodeJS.ReadableStream | undefined;
+    if (!source) {
+      const buffer = toBuffer(file);
+      if (buffer) return buffer;
+    }
+    if (!source) {
+      const maybeBuffer = toBuffer(
+        (file as any).buffer ??
+          (file as any).value ??
+          (file as any).data ??
+          undefined,
+      );
+      if (maybeBuffer) return maybeBuffer;
+      if (typeof (file as any).toBuffer === 'function') {
+        const buffer = await (file as any).toBuffer();
+        if (Buffer.isBuffer(buffer)) return buffer;
+      }
+    }
+    if (!source) {
+      throw new BadRequestException('Upload stream is missing');
+    }
+
+    const chunks: Buffer[] = [];
+    for await (const chunk of source) {
+      chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
+    }
+    return Buffer.concat(chunks);
+  }
+
+  async importExcelTags(file: MultipartFile) {
+    const buffer = await this.readUploadBuffer(file);
     if (!buffer.length) {
-      throw new BadRequestException('No file uploaded');
+      throw new BadRequestException('Empty file');
     }
 
     const workbook = XLSX.read(buffer, { type: 'buffer' });