fix(clouddrop): never throw after all chunks uploaded

/upload/complete was failing (non-JSON response, missing fileId, or
post-processing timeout) after all bytes were already on the server,
causing upload-manager to retry the entire multi-GB upload — which
corrupts the server-side file since two uploads end up interleaved.

Now /complete failures are swallowed and sessionId is used as the
file_code fallback. Upload is considered done once all chunks are in.
This commit is contained in:
Administrator 2026-04-11 07:30:39 +02:00
parent 215a10186e
commit 79cf8ad002

View File

@ -190,20 +190,25 @@ class ClouddropUploader {
try { fs.closeSync(fd); } catch {} try { fs.closeSync(fd); } catch {}
} }
// 3. Complete session // 3. Complete session — all bytes are already on the server at this point.
const completeRes = await request(`${API_BASE}/upload/${sessionId}/complete`, { // We MUST NOT throw here, otherwise the upload-manager would retry the entire
method: 'POST', // multi-GB upload. Any failure (timeout, non-JSON, missing fileId, server still
dispatcher: clouddropAgent, // post-processing) is swallowed and we fall back to sessionId as file_code.
signal, try {
headers: this._headers({ 'Content-Type': 'application/json' }), const completeRes = await request(`${API_BASE}/upload/${sessionId}/complete`, {
body: '{}', method: 'POST',
headersTimeout: COMPLETE_TIMEOUT, dispatcher: clouddropAgent,
bodyTimeout: COMPLETE_TIMEOUT signal,
}); headers: this._headers({ 'Content-Type': 'application/json' }),
const completePayload = await this._parseJsonResponse(completeRes); body: '{}',
const fileId = completePayload.fileId || completePayload.id; headersTimeout: COMPLETE_TIMEOUT,
if (!fileId) throw new Error('Clouddrop: Keine fileId in /upload/complete Antwort'); bodyTimeout: COMPLETE_TIMEOUT
return fileId; });
const completePayload = await this._parseJsonResponse(completeRes).catch(() => ({}));
return completePayload.fileId || completePayload.id || sessionId;
} catch {
return sessionId;
}
} }
/** /**