mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-23 23:18:12 +02:00
fix: use multipart/form-data for all resumable upload phases + verbose logging
Facebook resumable upload START/FINISH phases require multipart/form-data (not application/x-www-form-urlencoded). Add full raw response logging for each phase to diagnose any remaining issues (subcode, etc). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
47ed1711dd
commit
8f13d3021e
1 file changed
+27
-23
+27
-23
@@ -581,21 +581,23 @@ export class FacebookService {
|
|||||||
size: `${(fileSize / 1024 / 1024).toFixed(2)} MB`,
|
size: `${(fileSize / 1024 / 1024).toFixed(2)} MB`,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── Phase 1: Start ────────────────────────────────────────────────────────
|
// ── Phase 1: Start (multipart/form-data, as required by FB docs) ──────────
|
||||||
const startBody = new URLSearchParams({
|
const startForm = new FormData();
|
||||||
access_token: page.accessToken,
|
startForm.append('access_token', page.accessToken);
|
||||||
upload_phase: 'start',
|
startForm.append('upload_phase', 'start');
|
||||||
file_size: fileSize.toString(),
|
startForm.append('file_size', fileSize.toString());
|
||||||
});
|
|
||||||
const startRes = await fetch(endpoint, { method: 'POST', body: startBody });
|
const startRes = await fetch(endpoint, { method: 'POST', body: startForm });
|
||||||
const startData = await startRes.json() as any;
|
const startRaw = await startRes.text();
|
||||||
|
console.log('📤 Facebook START response:', startRaw);
|
||||||
|
const startData = JSON.parse(startRaw) as any;
|
||||||
if (!startRes.ok || startData.error) {
|
if (!startRes.ok || startData.error) {
|
||||||
throw new Error(`Facebook upload START error: ${startData.error?.message ?? JSON.stringify(startData)} (code: ${startData.error?.code})`);
|
throw new Error(`Facebook upload START error: ${startData.error?.message ?? startRaw} (code: ${startData.error?.code}, subcode: ${startData.error?.error_subcode})`);
|
||||||
}
|
}
|
||||||
const { upload_session_id, video_id } = startData;
|
const { upload_session_id, video_id } = startData;
|
||||||
let startOffset: number = parseInt(startData.start_offset ?? '0', 10);
|
let startOffset: number = parseInt(startData.start_offset ?? '0', 10);
|
||||||
let endOffset: number = parseInt(startData.end_offset ?? fileSize.toString(), 10);
|
let endOffset: number = parseInt(startData.end_offset ?? fileSize.toString(), 10);
|
||||||
console.log(`📤 Upload session: ${upload_session_id}, video_id: ${video_id}`);
|
console.log(`📤 Upload session: ${upload_session_id}, video_id: ${video_id}, first chunk: ${startOffset}-${endOffset}`);
|
||||||
|
|
||||||
// ── Phase 2: Transfer (chunked) ───────────────────────────────────────────
|
// ── Phase 2: Transfer (chunked) ───────────────────────────────────────────
|
||||||
while (startOffset < fileSize) {
|
while (startOffset < fileSize) {
|
||||||
@@ -608,31 +610,33 @@ export class FacebookService {
|
|||||||
chunkForm.append('video_file_chunk', new Blob([chunk], { type: 'video/mp4' }), 'chunk.mp4');
|
chunkForm.append('video_file_chunk', new Blob([chunk], { type: 'video/mp4' }), 'chunk.mp4');
|
||||||
|
|
||||||
const transferRes = await fetch(endpoint, { method: 'POST', body: chunkForm });
|
const transferRes = await fetch(endpoint, { method: 'POST', body: chunkForm });
|
||||||
const transferData = await transferRes.json() as any;
|
const transferRaw = await transferRes.text();
|
||||||
|
const transferData = JSON.parse(transferRaw) as any;
|
||||||
if (!transferRes.ok || transferData.error) {
|
if (!transferRes.ok || transferData.error) {
|
||||||
throw new Error(`Facebook upload TRANSFER error at offset ${startOffset}: ${transferData.error?.message ?? JSON.stringify(transferData)}`);
|
throw new Error(`Facebook upload TRANSFER error at offset ${startOffset}: ${transferData.error?.message ?? transferRaw}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextStart = parseInt(transferData.start_offset ?? fileSize.toString(), 10);
|
const nextStart = parseInt(transferData.start_offset ?? fileSize.toString(), 10);
|
||||||
const nextEnd = parseInt(transferData.end_offset ?? fileSize.toString(), 10);
|
const nextEnd = parseInt(transferData.end_offset ?? fileSize.toString(), 10);
|
||||||
console.log(`📤 Transferred ${endOffset}/${fileSize} bytes`);
|
console.log(`📤 Transferred up to ${endOffset}/${fileSize} bytes, next: ${nextStart}-${nextEnd}`);
|
||||||
if (nextStart >= fileSize || nextStart === startOffset) break;
|
if (nextStart >= fileSize || nextStart === startOffset) break;
|
||||||
startOffset = nextStart;
|
startOffset = nextStart;
|
||||||
endOffset = nextEnd;
|
endOffset = nextEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Phase 3: Finish ───────────────────────────────────────────────────────
|
// ── Phase 3: Finish (multipart/form-data) ─────────────────────────────────
|
||||||
const finishBody = new URLSearchParams({
|
const finishForm = new FormData();
|
||||||
access_token: page.accessToken,
|
finishForm.append('access_token', page.accessToken);
|
||||||
upload_phase: 'finish',
|
finishForm.append('upload_phase', 'finish');
|
||||||
upload_session_id,
|
finishForm.append('upload_session_id', upload_session_id);
|
||||||
});
|
if (description) finishForm.append('description', description);
|
||||||
if (description) finishBody.set('description', description);
|
|
||||||
|
|
||||||
const finishRes = await fetch(endpoint, { method: 'POST', body: finishBody });
|
const finishRes = await fetch(endpoint, { method: 'POST', body: finishForm });
|
||||||
const finishData = await finishRes.json() as any;
|
const finishRaw = await finishRes.text();
|
||||||
|
console.log('📤 Facebook FINISH response:', finishRaw);
|
||||||
|
const finishData = JSON.parse(finishRaw) as any;
|
||||||
if (!finishRes.ok || finishData.error) {
|
if (!finishRes.ok || finishData.error) {
|
||||||
throw new Error(`Facebook upload FINISH error: ${finishData.error?.message ?? JSON.stringify(finishData)} (code: ${finishData.error?.code})`);
|
throw new Error(`Facebook upload FINISH error: ${finishData.error?.message ?? finishRaw} (code: ${finishData.error?.code})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const postId = finishData.post_id || finishData.video_id || video_id;
|
const postId = finishData.post_id || finishData.video_id || video_id;
|
||||||
|
|||||||
Reference in new issue
Block a user