feat(nextcloud-files): Dateien auflisten, Vorschau, Ordner anlegen, umbenennen, verschieben und löschen
- PROPFIND-Auswertung (mehrere propstat, Kleinbuchstaben-Hex, Speicher -3 = unbegrenzt, nur Zeichenketten) - WebDAV-Schicht mit Zugangsschluessel und Aufrufsperre, Destination immer aus der Basis, Overwrite: F - mapNcFailure als einzige Fehlerabbildung (nie 401/403 an den Browser), sendUpstreamStream prueft vor dem ersten Byte - Dateidienst und Routen files, folders, move, preview im eigenen Konto; zweiter Benutzer bekommt notConnected - Web-API-Funktionen listFolder, createFolder, moveEntry, deleteEntry, previewUrl - e2e-files.sh gegen die Test-Nextcloud Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -163,3 +163,67 @@ export function cancelLoginFlow(flowId: string): Promise<{ cancelled: true }> {
|
||||
export function disconnectNextcloud(): Promise<{ disconnected: true }> {
|
||||
return request<{ disconnected: true }>('/connect', { method: 'DELETE' });
|
||||
}
|
||||
|
||||
// --- Dateien (Etappe 1, Aufgabe 3) -------------------------------------------------------------
|
||||
|
||||
export interface NcEntry {
|
||||
name: string;
|
||||
/** Pfad ab der Wurzel, z. B. `/Projekte/Bericht.pdf`. */
|
||||
path: string;
|
||||
type: 'folder' | 'file';
|
||||
size: number;
|
||||
mime: string | null;
|
||||
/** ISO-Zeitstempel. */
|
||||
mtime: string | null;
|
||||
etag: string | null;
|
||||
fileId: string | null;
|
||||
/** Berechtigungsbuchstaben der Nextcloud (R teilbar, D loeschbar, N umbenennbar ...). */
|
||||
permissions: string;
|
||||
hasPreview: boolean;
|
||||
favorite: boolean;
|
||||
}
|
||||
|
||||
export interface NcQuota {
|
||||
used: number;
|
||||
/** null = unbegrenzt oder unbekannt. */
|
||||
available: number | null;
|
||||
}
|
||||
|
||||
export interface NcListing {
|
||||
path: string;
|
||||
entries: NcEntry[];
|
||||
quota: NcQuota;
|
||||
/** true, wenn der Ordner mehr als 5000 Eintraege hat und abgeschnitten wurde. */
|
||||
truncated: boolean;
|
||||
}
|
||||
|
||||
/** Ordnerinhalt samt Speicherangaben. Der Pfad geht nur in der Query, nie im URL-Pfad. */
|
||||
export function listFolder(path: string): Promise<NcListing> {
|
||||
return request<NcListing>(`/files?path=${encodeURIComponent(path)}`);
|
||||
}
|
||||
|
||||
export function createFolder(path: string): Promise<{ path: string }> {
|
||||
return request<{ path: string }>('/folders', { method: 'POST', json: { path } });
|
||||
}
|
||||
|
||||
/** Verschieben oder Umbenennen; ein vorhandener Name im Ziel wird nie ueberschrieben (nameTaken). */
|
||||
export function moveEntry(from: string, to: string): Promise<{ from: string; to: string }> {
|
||||
return request<{ from: string; to: string }>('/move', { method: 'POST', json: { from, to } });
|
||||
}
|
||||
|
||||
/** Loescht in den Papierkorb der Nextcloud. */
|
||||
export function deleteEntry(path: string): Promise<{ deleted: true }> {
|
||||
return request<{ deleted: true }>(`/files?path=${encodeURIComponent(path)}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adresse des Vorschaubildes fuer ein `<img>` (Tessera-Cookie genuegt). Die
|
||||
* Version (Entity-Tag) macht die Adresse je Dateiversion eindeutig und erlaubt
|
||||
* dem Browser, das Bild zu cachen.
|
||||
*/
|
||||
export function previewUrl(fileId: string, etag: string | null): string {
|
||||
const version = etag ? `&v=${encodeURIComponent(etag)}` : '';
|
||||
return `${API_URL}${BASE}/preview?fileId=${encodeURIComponent(fileId)}${version}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user