fix of the json upload format
This commit is contained in:
@@ -48,7 +48,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// 1. Ein echter CSV-Parser, der Zeilenumbrüche und Kommas in Texten korrekt ignoriert
|
// 1. Robuster CSV-Parser, der Zeilenumbrüche und Kommas in Texten korrekt ignoriert
|
||||||
function parseCSV(csvString) {
|
function parseCSV(csvString) {
|
||||||
const rows = [];
|
const rows = [];
|
||||||
let currentRow = [];
|
let currentRow = [];
|
||||||
@@ -70,7 +70,6 @@ function parseCSV(csvString) {
|
|||||||
} else if ((char === '\n' || char === '\r') && !insideQuotes) {
|
} else if ((char === '\n' || char === '\r') && !insideQuotes) {
|
||||||
if (char === '\r' && nextChar === '\n') i++; // Windows Umbrüche überspringen
|
if (char === '\r' && nextChar === '\n') i++; // Windows Umbrüche überspringen
|
||||||
currentRow.push(currentCell);
|
currentRow.push(currentCell);
|
||||||
// Leere Zeilen ignorieren
|
|
||||||
if (currentRow.length > 1 || currentRow[0] !== '') {
|
if (currentRow.length > 1 || currentRow[0] !== '') {
|
||||||
rows.push(currentRow);
|
rows.push(currentRow);
|
||||||
}
|
}
|
||||||
@@ -94,7 +93,6 @@ function rowToCSV(rowArray) {
|
|||||||
return rowArray.map(cell => {
|
return rowArray.map(cell => {
|
||||||
if (cell === null || cell === undefined) return '';
|
if (cell === null || cell === undefined) return '';
|
||||||
let cellStr = String(cell);
|
let cellStr = String(cell);
|
||||||
// Wenn kritische Zeichen drin sind, sauber in Anführungszeichen verpacken
|
|
||||||
if (cellStr.includes(',') || cellStr.includes('"') || cellStr.includes('\n') || cellStr.includes('\r')) {
|
if (cellStr.includes(',') || cellStr.includes('"') || cellStr.includes('\n') || cellStr.includes('\r')) {
|
||||||
return '"' + cellStr.replace(/"/g, '""') + '"';
|
return '"' + cellStr.replace(/"/g, '""') + '"';
|
||||||
}
|
}
|
||||||
@@ -102,7 +100,7 @@ function rowToCSV(rowArray) {
|
|||||||
}).join(',');
|
}).join(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Bildnamen extrahieren (bleibt wie es war)
|
// 3. Bildnamen extrahieren
|
||||||
function extractImageNames(cellValue) {
|
function extractImageNames(cellValue) {
|
||||||
if (!cellValue) return [];
|
if (!cellValue) return [];
|
||||||
let raw = String(cellValue).replace(/^["']|["']$/g, '').trim();
|
let raw = String(cellValue).replace(/^["']|["']$/g, '').trim();
|
||||||
@@ -159,7 +157,6 @@ document.getElementById('batchUploadForm').addEventListener('submit', async func
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const csvText = await csvFile.text();
|
const csvText = await csvFile.text();
|
||||||
// Hier rufen wir jetzt unseren sicheren Parser auf!
|
|
||||||
const allRows = parseCSV(csvText);
|
const allRows = parseCSV(csvText);
|
||||||
|
|
||||||
if (allRows.length <= 1) {
|
if (allRows.length <= 1) {
|
||||||
@@ -171,10 +168,8 @@ document.getElementById('batchUploadForm').addEventListener('submit', async func
|
|||||||
|
|
||||||
log(`${dataRows.length} Einträge gefunden. Bereite Batches vor...`);
|
log(`${dataRows.length} Einträge gefunden. Bereite Batches vor...`);
|
||||||
|
|
||||||
// Spalten-Index von "Images" sicher ermitteln
|
|
||||||
const imagesColIndex = headerRow.findIndex(h => h.toLowerCase().trim() === 'images');
|
const imagesColIndex = headerRow.findIndex(h => h.toLowerCase().trim() === 'images');
|
||||||
|
|
||||||
// In Batches aufteilen
|
|
||||||
const batches = [];
|
const batches = [];
|
||||||
for (let i = 0; i < dataRows.length; i += BATCH_SIZE) {
|
for (let i = 0; i < dataRows.length; i += BATCH_SIZE) {
|
||||||
batches.push(dataRows.slice(i, i + BATCH_SIZE));
|
batches.push(dataRows.slice(i, i + BATCH_SIZE));
|
||||||
@@ -183,10 +178,12 @@ document.getElementById('batchUploadForm').addEventListener('submit', async func
|
|||||||
progressBar.max = batches.length;
|
progressBar.max = batches.length;
|
||||||
progressBar.value = 0;
|
progressBar.value = 0;
|
||||||
|
|
||||||
|
// Sequenzieller Upload mit Fehlertoleranz pro Batch
|
||||||
for (let b = 0; b < batches.length; b++) {
|
for (let b = 0; b < batches.length; b++) {
|
||||||
const batchRows = batches[b];
|
const batchRows = batches[b];
|
||||||
progressText.textContent = `Lade Batch ${b + 1} von ${batches.length} hoch...`;
|
progressText.textContent = `Lade Batch ${b + 1} von ${batches.length} hoch...`;
|
||||||
|
|
||||||
|
try {
|
||||||
const requiredImagesForBatch = new Set();
|
const requiredImagesForBatch = new Set();
|
||||||
|
|
||||||
if (imagesColIndex !== -1) {
|
if (imagesColIndex !== -1) {
|
||||||
@@ -203,7 +200,6 @@ document.getElementById('batchUploadForm').addEventListener('submit', async func
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sicherer Zusammenbau des CSV-Batches
|
|
||||||
const batchCsvArray = [headerRow, ...batchRows];
|
const batchCsvArray = [headerRow, ...batchRows];
|
||||||
const batchCsvText = batchCsvArray.map(rowToCSV).join('\n');
|
const batchCsvText = batchCsvArray.map(rowToCSV).join('\n');
|
||||||
const batchCsvBlob = new Blob([batchCsvText], { type: 'text/csv' });
|
const batchCsvBlob = new Blob([batchCsvText], { type: 'text/csv' });
|
||||||
@@ -221,7 +217,6 @@ document.getElementById('batchUploadForm').addEventListener('submit', async func
|
|||||||
|
|
||||||
log(`Batch ${b + 1}: ${batchRows.length} Items & ${requiredImagesForBatch.size} zugehörige Bilder.`);
|
log(`Batch ${b + 1}: ${batchRows.length} Items & ${requiredImagesForBatch.size} zugehörige Bilder.`);
|
||||||
|
|
||||||
// Request absenden
|
|
||||||
const response = await fetch('/upload_csv_batch', {
|
const response = await fetch('/upload_csv_batch', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData,
|
body: formData,
|
||||||
@@ -230,27 +225,30 @@ document.getElementById('batchUploadForm').addEventListener('submit', async func
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1. Antwort als rohen Text auslesen (verhindert den JSON.parse Crash)
|
|
||||||
const responseText = await response.text();
|
const responseText = await response.text();
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = JSON.parse(responseText);
|
result = JSON.parse(responseText);
|
||||||
} catch (parseErr) {
|
} catch (parseErr) {
|
||||||
// Wenn der Server kein JSON schickt (z.B. Python 500 Error als HTML-Seite)
|
throw new Error(`Server-Fehler (Status ${response.status}). HTML statt JSON erhalten.`);
|
||||||
console.error("Server-Antwort war kein JSON:", responseText);
|
|
||||||
throw new Error(`Server-Fehler (Status ${response.status}). Der Server hat ein HTML-Dokument statt JSON zurückgegeben. Prüfe die Flask-Konsole!`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response.ok || !result.success) {
|
if (!response.ok || !result.success) {
|
||||||
throw new Error(result.message || `Server-Fehler ${response.status}`);
|
throw new Error(result.message || `Server-Fehler ${response.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`Batch ${b + 1} abgeschlossen: ${result.message}`);
|
log(`Batch ${b + 1} erfolgreich abgeschlossen.`);
|
||||||
|
|
||||||
|
} catch (batchErr) {
|
||||||
|
log(`⚠️ FEHLER in Batch ${b + 1}: ${batchErr.message}. Überspringe und fahre fort...`);
|
||||||
|
console.error(`Batch ${b + 1} fehlgeschlagen:`, batchErr);
|
||||||
|
}
|
||||||
|
|
||||||
progressBar.value = b + 1;
|
progressBar.value = b + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
progressText.textContent = "Upload erfolgreich beendet! Keine verschobenen Spalten mehr.";
|
progressText.textContent = "Upload-Prozess beendet!";
|
||||||
uploadBtn.disabled = false;
|
uploadBtn.disabled = false;
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
Reference in New Issue
Block a user