Bibliothek: eindeutige Namen auch für Auswahl-ZIPs
Dieselbe Schwäche eine Ebene weiter: Jedes ZIP aus der Bibliothek hieß `klarbild_2026-09-01.zip`, zwei verschiedene Auswahlen am selben Tag im selben Ordner überschrieben sich also. Jetzt `2026-09-01_143207_auswahl-12-bilder_a3f9.zip`, und der Client liest den Namen aus dem Kopf statt einen eigenen zu bauen. 124 Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BNhLunz586g6DeYMa7Qsd1
This commit is contained in:
4 files changed
+30
-3
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { nameAusKopf } from '../lib/naming';
|
||||
import ShareDialog, { type ShareZiel } from './ShareDialog';
|
||||
|
||||
interface Item { id: string; filename: string; output_px: string; has_alpha: boolean;
|
||||
@@ -77,7 +78,9 @@ export default function LibraryApp() {
|
||||
if (!res.ok) { notify('ZIP fehlgeschlagen.'); return; }
|
||||
const blob = await res.blob();
|
||||
const a = document.createElement('a'); a.href = URL.createObjectURL(blob);
|
||||
a.download = `klarbild_${new Date().toISOString().slice(0, 10)}.zip`; a.click();
|
||||
// Der Name kommt vom Server — hier einen eigenen zu bauen hieße, zwei
|
||||
// Auswahlen desselben Tages wieder gleich zu nennen.
|
||||
a.download = nameAusKopf(res.headers.get('Content-Disposition'), 'klarbild-auswahl.zip'); a.click();
|
||||
URL.revokeObjectURL(a.href); notify('ZIP geladen.');
|
||||
};
|
||||
const alternative = async (id: string) => {
|
||||
|
||||
@@ -230,3 +230,15 @@ export function nameAusKopf(header: string | null | undefined, fallback: string)
|
||||
function sicher(n: string): string {
|
||||
return n.replace(/[\\/\r\n\0]/g, '').replace(/^\.+/, '').trim().slice(0, 120);
|
||||
}
|
||||
|
||||
/**
|
||||
* Name für ein ZIP aus einer Auswahl in der Bibliothek:
|
||||
* `2026-09-01_143207_auswahl-12-bilder_a3f9.zip`
|
||||
*
|
||||
* Vorher hieß jedes `klarbild_2026-09-01.zip` — zwei verschiedene Auswahlen am
|
||||
* selben Tag im selben Ordner, und die zweite überschrieb die erste.
|
||||
*/
|
||||
export function buildAuswahlZipName(anzahl: number, at: Date = new Date()): string {
|
||||
const was = anzahl === 1 ? 'auswahl-1-bild' : `auswahl-${anzahl}-bilder`;
|
||||
return `${timeStamp(at)}_${was}_${shortTag(null)}.zip`;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { buildAuswahlZipName } from '../../../lib/naming';
|
||||
import archiver from 'archiver';
|
||||
import { query } from '../../../lib/db';
|
||||
import { getObject } from '../../../lib/storage';
|
||||
@@ -40,11 +41,12 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
||||
done.catch(() => {});
|
||||
},
|
||||
});
|
||||
const stamp = new Date().toISOString().slice(0, 10);
|
||||
// Eindeutig statt nur datiert: Zwei Auswahlen desselben Tages hießen gleich.
|
||||
const name = buildAuswahlZipName(rows.length);
|
||||
return new Response(stream, {
|
||||
headers: {
|
||||
'Content-Type': 'application/zip',
|
||||
'Content-Disposition': `attachment; filename="klarbild_${stamp}.zip"`,
|
||||
'Content-Disposition': `attachment; filename="${name}"`,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -91,3 +91,13 @@ test('Ein Name aus dem Kopf kann keinen Pfad einschleusen', () => {
|
||||
assert.ok(!n.includes('/') && !n.includes('\\') && !n.startsWith('.'), `Pfad überlebt: ${n}`);
|
||||
}
|
||||
});
|
||||
|
||||
test('ZIPs aus der Bibliothek heißen nicht alle gleich', async () => {
|
||||
const { buildAuswahlZipName } = await import('../src/lib/naming.ts');
|
||||
const a = buildAuswahlZipName(12, AM);
|
||||
assert.match(a, /^2026-09-01_143207_auswahl-12-bilder_[0-9a-f]{4}\.zip$/);
|
||||
assert.equal(buildAuswahlZipName(1, AM).includes('auswahl-1-bild_'), true);
|
||||
// Zwei Auswahlen derselben Sekunde: das Kürzel unterscheidet sie.
|
||||
const paare = new Set(Array.from({ length: 50 }, () => buildAuswahlZipName(12, AM)));
|
||||
assert.ok(paare.size > 40, `zu viele gleiche Namen: ${paare.size}/50`);
|
||||
});
|
||||
Reference in new issue
Block a user