|
@@ -358,42 +358,72 @@ export class VideoMediaService {
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
const rowsAH: Array<{ idRaw: unknown; tagsRaw: unknown }> = [];
|
|
const rowsAH: Array<{ idRaw: unknown; tagsRaw: unknown }> = [];
|
|
|
- const csvText = buffer.toString('utf8');
|
|
|
|
|
- const lines = csvText.split(/\r?\n/);
|
|
|
|
|
- const parseCsvLine = (line: string): string[] => {
|
|
|
|
|
- const cells: string[] = [];
|
|
|
|
|
- let current = '';
|
|
|
|
|
- let inQuotes = false;
|
|
|
|
|
- for (let i = 0; i < line.length; i += 1) {
|
|
|
|
|
- const ch = line[i];
|
|
|
|
|
- if (ch === '"') {
|
|
|
|
|
- if (inQuotes && line[i + 1] === '"') {
|
|
|
|
|
- current += '"';
|
|
|
|
|
- i += 1;
|
|
|
|
|
- } else {
|
|
|
|
|
- inQuotes = !inQuotes;
|
|
|
|
|
|
|
+ const filename = (file as any)?.filename ?? '';
|
|
|
|
|
+ const looksLikeXlsx =
|
|
|
|
|
+ buffer.length >= 4 &&
|
|
|
|
|
+ buffer[0] === 0x50 &&
|
|
|
|
|
+ buffer[1] === 0x4b &&
|
|
|
|
|
+ buffer[2] === 0x03 &&
|
|
|
|
|
+ buffer[3] === 0x04;
|
|
|
|
|
+
|
|
|
|
|
+ if (looksLikeXlsx || /\.xlsx$/i.test(filename)) {
|
|
|
|
|
+ const workbook = XLSX.read(buffer, { type: 'buffer' });
|
|
|
|
|
+ const sheetName = workbook.SheetNames[0];
|
|
|
|
|
+ const sheet = sheetName ? workbook.Sheets[sheetName] : undefined;
|
|
|
|
|
+
|
|
|
|
|
+ if (!sheet) {
|
|
|
|
|
+ throw new BadRequestException('No sheet found in Excel file');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const rangeRef = sheet['!ref'] ?? 'A1:A1';
|
|
|
|
|
+ const range = XLSX.utils.decode_range(rangeRef);
|
|
|
|
|
+
|
|
|
|
|
+ for (let r = range.s.r; r <= range.e.r; r += 1) {
|
|
|
|
|
+ const idCell = sheet[XLSX.utils.encode_cell({ r, c: 0 })];
|
|
|
|
|
+ const tagsCell = sheet[XLSX.utils.encode_cell({ r, c: 7 })];
|
|
|
|
|
+ rowsAH.push({
|
|
|
|
|
+ idRaw: idCell?.v ?? '',
|
|
|
|
|
+ tagsRaw: tagsCell?.v ?? '',
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const csvText = buffer.toString('utf8');
|
|
|
|
|
+ const lines = csvText.split(/\r?\n/);
|
|
|
|
|
+ const parseCsvLine = (line: string): string[] => {
|
|
|
|
|
+ const cells: string[] = [];
|
|
|
|
|
+ let current = '';
|
|
|
|
|
+ let inQuotes = false;
|
|
|
|
|
+ for (let i = 0; i < line.length; i += 1) {
|
|
|
|
|
+ const ch = line[i];
|
|
|
|
|
+ if (ch === '"') {
|
|
|
|
|
+ if (inQuotes && line[i + 1] === '"') {
|
|
|
|
|
+ current += '"';
|
|
|
|
|
+ i += 1;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ inQuotes = !inQuotes;
|
|
|
|
|
+ }
|
|
|
|
|
+ continue;
|
|
|
}
|
|
}
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- if (ch === ',' && !inQuotes) {
|
|
|
|
|
- cells.push(current);
|
|
|
|
|
- current = '';
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ if (ch === ',' && !inQuotes) {
|
|
|
|
|
+ cells.push(current);
|
|
|
|
|
+ current = '';
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ current += ch;
|
|
|
}
|
|
}
|
|
|
- current += ch;
|
|
|
|
|
- }
|
|
|
|
|
- cells.push(current);
|
|
|
|
|
- return cells;
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ cells.push(current);
|
|
|
|
|
+ return cells;
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- for (let i = 1; i < lines.length; i += 1) {
|
|
|
|
|
- const line = lines[i];
|
|
|
|
|
- if (!line) continue;
|
|
|
|
|
- const cells = parseCsvLine(line);
|
|
|
|
|
- rowsAH.push({
|
|
|
|
|
- idRaw: cells[0] ?? '',
|
|
|
|
|
- tagsRaw: cells[7] ?? '',
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ for (let i = 1; i < lines.length; i += 1) {
|
|
|
|
|
+ const line = lines[i];
|
|
|
|
|
+ if (!line) continue;
|
|
|
|
|
+ const cells = parseCsvLine(line);
|
|
|
|
|
+ rowsAH.push({
|
|
|
|
|
+ idRaw: cells[0] ?? '',
|
|
|
|
|
+ tagsRaw: cells[7] ?? '',
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.logger.log(
|
|
this.logger.log(
|