העלאת קובץ בapi לימות המשיח | קוד שבפייתון עובד וב nodejs לא כל כך
-
@dovid כתב בהעלאת קובץ בapi לימות המשיח | קוד שבפייתון עובד וב nodejs לא כל כך:
קיבלתי את הקוד מ@צבי-ש ויש שגיאה מצד ימות, עם הודעה Syste, error, וmessageCode 105.
בקוד המקורי שהעלתי פה אין שגיאה כזאת, אלא על כל חלק וחלק אני מקבל תשובה שהכל תקין, וגם בסוף שעלה בסדר, שולח גם את הנתיב של הקובץ, אבל מעלה אותו עם 0kb
מה שיוצר לי תחושה כאילו אני סתם מחלק את הקובץ לחלקים, כשבפועל בכל קריאה אני מעלה 0kb
(תוכל לראות בשלוחה 1 שם קובץ כזה) -
עובד לי כעת קובץ בודד, בתנאי שאני מציין את שם הקובץ לFormData. הנה הקוד המעודכן:
import fs from 'fs/promises'; import fetch from 'node-fetch'; import FormData from 'form-data'; async function* getChunks(filePath, chunkSize = 5000000) { const file = await fs.open(filePath, 'r'); const buffer = Buffer.alloc(chunkSize); while (true) { const result = await file.read(buffer, 0, chunkSize); if (result.bytesRead === chunkSize) yield result.buffer; else { yield result.buffer.slice(0, result.bytesRead); break; } } await file.close(); } function createFormData(bytes, contentName, partialData = null) { const formData = new FormData(); formData.append('token', tokenYemot); formData.append('path', remotePath); formData.append('convertAudio', 1); formData.append('autoNumbering', 1); if (partialData) { formData.append('qquuid', partialData.uuid); formData.append('qqfilename', contentName); formData.append('qqtotalfilesize', partialData.fileSize); formData.append('qqtotalparts', partialData.partCount); formData.append('qqchunksize', chunkSize); //in final post request we don't need to send the file if (partialData.partCount > (partialData.part + 1)) { formData.append('qqpartbyteoffset', chunkSize * partialData.part); formData.append('qqpartindex', partialData.part); formData.append('qqfile', bytes, contentName); } } else formData.append('file', bytes, contentName); return formData; } const tokenYemot = ''; const chunkSize = 5000000; const remotePath = 'ivr2:/'; async function uploadFile(filePath) { const fileSize = (await fs.stat(filePath)).size; const callApi = (url, payload) => fetch(url, {method: 'POST', body: payload}); const chunks = getChunks(filePath, chunkSize); const contentName = filePath.split('/').pop(); if (fileSize <= chunkSize) { const formData = createFormData((await chunks.next()).value, contentName); return await callApi('https://www.call2all.co.il/ym/api/UploadFile', formData).then(x => x.json()); } else { const uuid = crypto.randomUUID(); const partCount = Math.ceil(chunkSize / fileSize); let part = 0; for await (const chunk of chunks) { const formData = createFormData(chunk, contentName, { uuid, fileSize, partCount, part}); part++; const status = await callApi('https://www.call2all.co.il/ym/api/UploadFile', formData).then(x => x.json()); if(!status.success){ console.log(status); throw new Error(status.message); } } return await callApi('https://www.call2all.co.il/ym/api/UploadFile?done', createFormData(null, { uuid, fileSize, partCount, part})).then(x => x.json()); } } const result = await uploadFile("D:/testS.mp3"); console.log(result);
-
פוסט זה נמחק!
-
@צבי-ש בשורה 55 תחליף מ:
formData.append('qqfile', chunk)
ל:
formData.append('qqfile', chunk, { filename: contentName, contentType: 'application/octet-stream', });
-
סליחה על המענה המאוחר, אני השתמשתי בפיתרון ש @ivrtikshoret כתב פה,
עבד לי מעולה, ערכתי את הפונקציה שתתאים גם לקבצים קטנים יותר.const readInChunks = (filePath, chunkSize = 5000000) => { const file = fs.readFileSync(filePath); const chunks = []; for (let offset = 0; offset < file.length; offset += chunkSize) { const chunk = file.slice(offset, offset + chunkSize); chunks.push(chunk); } return chunks; }; export const uploadFileInYemot = async (filePath, path, tokenYemot) => { const fileSize = fs.statSync(filePath).size; const contentName = filePath.split('/').pop(); if (fileSize <= 5000000) { const formData = new FormData(); formData.append('token', tokenYemot); formData.append('path', path); formData.append('convertAudio', 1); formData.append('autoNumbering', 1); formData.append('file', fs.readFileSync(filePath), { filename: contentName, contentType: 'application/octet-stream', }); const response = await fetch('https://www.call2all.co.il/ym/api/UploadFile', { method: 'POST', body: formData, }); return await response.json(); } else { const chunks = readInChunks(filePath); const qquuid = uuidv4().toString(); for (let i = 0; i < chunks.length; i++) { const chunk = chunks[i]; const formData = new FormData(); formData.append('token', tokenYemot); formData.append('path', path); formData.append('qquuid', qquuid); formData.append('convertAudio', 0); formData.append('autoNumbering', 'true'); formData.append('uploader', 'yemot-admin'); formData.append('qqfilename', contentName); formData.append('qqtotalfilesize', fileSize); formData.append('qqtotalparts', chunks.length); formData.append('qqchunksize', chunk.length); formData.append('qqpartbyteoffset', i * chunk.length); formData.append('qqpartindex', i); formData.append('qqfile', chunk, { filename: contentName, contentType: 'application/octet-stream', }); const response = await fetch('https://www.call2all.co.il/ym/api/UploadFile', { method: 'POST', body: formData, }); const responseData = await response.json(); console.log(responseData); } const finalFormData = new FormData(); finalFormData.append('token', tokenYemot); finalFormData.append('path', path); finalFormData.append('uploader', 'yemot-admin'); finalFormData.append('convertAudio', '0'); finalFormData.append('autoNumbering', 'true'); finalFormData.append('qquuid', qquuid); finalFormData.append('qqfilename', contentName); finalFormData.append('qqtotalfilesize', fileSize); finalFormData.append('qqtotalparts', chunks.length); try { const response = await fetch('https://www.call2all.co.il/ym/api/UploadFile?done', { method: 'POST', body: finalFormData, }); const responseData = await response.text(); console.log(responseData); } catch (error) { console.error("Error during the fetch:", error); } } };
תודה לכל העוזרים.
נ.ב. תודה למי שפנה אליי באישי והאיר לי על הנושא.
-
מעלה את הקוד המתוקן שלי שמציע כמה שיפורים, ב"ה כעת זה עובד.
import fs from 'fs/promises'; const baseUrl = 'https://www.call2all.co.il'; async function* getChunks(filePath, chunkSize) { const file = await fs.open(filePath, 'r'); const buffer = Buffer.alloc(chunkSize); try { while (true) { const result = await file.read(buffer, 0, chunkSize); if (result.bytesRead === chunkSize) yield result.buffer; else { yield result.buffer.slice(0, result.bytesRead); break; } } } finally { await file.close(); } } function createFormData(bytes, contentName, partialData = null) { const data = { token: tokenYemot, path: remotePath, convertAudio: 1, autoNumbering: 0 }; if (partialData) { data.uploader = 'yemot-admin'; data.qquuid = partialData.uuid; data.qqfilename = contentName; data.qqtotalfilesize = partialData.fileSize; data.qqtotalparts = partialData.partCount; //in final post request we don't need to send the file if (partialData.part < partialData.partCount) { data.qqpartbyteoffset = chunkSize * partialData.part; data.qqpartindex = partialData.part; data.qqchunksize = bytes.length; } } const formData = new FormData(); for (const [key, value] of Object.entries(data)) formData.append(key, value); if(bytes) formData.append( partialData ? 'qqfile' : 'file', new Blob([bytes]), {filename: contentName, contentType: 'application/octet-stream'}); return formData; } let tokenYemot = ''; const chunkSize = 20000000; const remotePath = 'ivr2:/'; async function uploadFile(filePath) { const fileSize = (await fs.stat(filePath)).size; const callApi = (url, payload) => fetch(url, {method: 'POST', body: payload}); const chunks = getChunks(filePath, chunkSize); const contentName = filePath.split('/').pop(); if (fileSize <= chunkSize) { const formData = createFormData((await chunks.next()).value, contentName); await chunks.return(); return await callApi(baseUrl + '/ym/api/UploadFile', formData).then(x => x.json()); } else { const uuid = crypto.randomUUID(); const partCount = Math.ceil(fileSize / chunkSize); let part = 0; for await (const chunk of chunks) { const formData = createFormData(chunk, contentName, {uuid, fileSize, partCount, part: part++}); const status = await callApi(baseUrl + '/ym/api/UploadFile', formData).then(x => x.json()); if (!status.success) { console.log(status); throw new Error(status.message); } } return await callApi(baseUrl + '/ym/api/UploadFile?done', createFormData(null, contentName, {uuid, fileSize, partCount, part})).then(x => x.text()); } }