Last active
November 14, 2023 11:04
-
-
Save mxsgx/1f306576c8ce25e5a99e35546220bc26 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const axios = require("axios"); | |
const fs = require("fs"); | |
/** | |
* @param {string} baseUrl Base URL of API (example: `https://peertube.cpy.re/api/v1`) | |
* @param {string} bearerToken Access token | |
* @param {string} filePath Pathlike file video want to upload | |
* @param {number} chunkSize Chunk size in bytes | |
* @param {number} channelId | |
* @param {string} fileName | |
* @param {string} name | |
* @returns {Promise<void>} | |
*/ | |
async function uploadResumableFile( | |
baseUrl, | |
bearerToken, | |
filePath, | |
chunkSize, | |
channelId, | |
fileName, | |
name | |
) { | |
try { | |
const url = new URL(baseUrl); | |
const fileSize = fs.statSync(filePath).size; | |
const client = axios.default.create({ | |
baseURL: baseUrl, | |
headers: { | |
Authorization: `Bearer ${bearerToken}`, | |
}, | |
validateStatus: function (status) { | |
return status < 400; | |
}, | |
}); | |
const resumableVideoResponse = await client.post( | |
"/videos/upload-resumable", | |
{ | |
channelId, | |
filename: fileName, | |
name, | |
}, | |
{ | |
headers: { | |
"X-Upload-Content-Length": fileSize, | |
"X-Upload-Content-Type": "video/mp4", | |
}, | |
} | |
); | |
if (resumableVideoResponse.status != 201) { | |
throw new Error("Failed to initialize resumable video"); | |
} | |
const resumableUplaodId = new URL( | |
`${url.protocol}${resumableVideoResponse.headers.get("location")}` | |
).searchParams.get("upload_id"); | |
const fileStream = fs.createReadStream(filePath, { | |
highWaterMark: chunkSize, | |
}); | |
let bytesRangeStart = 0; | |
fileStream.on("data", (chunk) => { | |
fileStream.pause(); | |
const bytesRangeEnd = bytesRangeStart + chunk.length - 1; | |
client | |
.put(`/videos/upload-resumable?upload_id=${resumableUplaodId}`, chunk, { | |
headers: { | |
"Content-Type": "application/octet-stream", | |
"Content-Length": chunk.length, | |
"Content-Range": `bytes ${bytesRangeStart}-${bytesRangeEnd}/${fileSize}`, | |
}, | |
}) | |
.then(() => { | |
console.log( | |
`Uploaded range ${bytesRangeStart}-${bytesRangeEnd}/${fileSize}` | |
); | |
bytesRangeStart += chunk.length; | |
fileStream.resume(); | |
}) | |
.catch((err) => { | |
fileStream.destroy(err); | |
}); | |
}); | |
fileStream.on("error", (err) => { | |
throw err; | |
}); | |
} catch (e) { | |
throw e; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment