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