Skip to content

Commit

Permalink
Merge pull request #74 from shhossain/master
Browse files Browse the repository at this point in the history
Add support for resumable downloads in app.js
  • Loading branch information
mifi authored Mar 17, 2024
2 parents 897f057 + f9dfd2d commit a877c3e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 9 deletions.
50 changes: 43 additions & 7 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const bodyParser = require('body-parser');
const filenamify = require('filenamify');
const util = require('util');
const stream = require('stream');
const parseRange = require('range-parser');


const pipeline = util.promisify(stream.pipeline);

Expand Down Expand Up @@ -114,22 +116,56 @@ module.exports = ({ sharedPath: sharedPathIn, port, maxUploadSize, zipCompressio
await promise;
}

async function serveResumableFileDownload({ filePath, range, res, forceDownload }) {
if (forceDownload) {
// Set the filename in the Content-disposition header
res.set('Content-disposition', contentDisposition(basename(filePath)));
}

const { size: fileSize } = await fs.stat(filePath);

if (range) {
const subranges = parseRange(fileSize, range);
if (subranges.type !== 'bytes') throw new Error(`Invalid range type ${subranges.type}`);

if (subranges.length !== 1) throw new Error('Only a single range is supported');
const [{ start, end }] = subranges;

const contentLength = (end - start) + 1;

// Set headers for resumable download
res.status(206).set({
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
'Accept-Ranges': 'bytes',
'Content-Length': contentLength,
'Content-Type': 'application/octet-stream',
});

await pipeline(fs.createReadStream(filePath, { start, end }), res);
} else {
// Standard download without resuming
res.set({
// 'Content-Type': 'application/octet-stream',
'Content-Length': fileSize,
});

await pipeline(fs.createReadStream(filePath), res);
}
}

app.get('/api/download', asyncHandler(async (req, res) => {
const filePath = getFilePath(req.query.f);
const forceDownload = req.query.forceDownload === 'true';
const isDir = await isDirectory(filePath);

if (isDir) {
await serveDirZip(filePath, res);
} else {
if (forceDownload) {
// NOTE: Must support non latin characters
res.set('Content-disposition', contentDisposition(basename(filePath)));
}

await pipeline(fs.createReadStream(filePath), res);
const { range } = req.headers;
await serveResumableFileDownload({ filePath, range, res, forceDownload });
}
}));


app.get('/api/browse', asyncHandler(async (req, res) => {
const curRelPath = req.query.p || '/';
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"meow": "^6.1.0",
"morgan": "^1.9.1",
"p-map": "^4.0.0",
"qrcode-terminal": "^0.12.0"
"qrcode-terminal": "^0.12.0",
"range-parser": "^1.2.1"
},
"devDependencies": {
"concurrently": "^5.1.0"
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ __metadata:
morgan: "npm:^1.9.1"
p-map: "npm:^4.0.0"
qrcode-terminal: "npm:^0.12.0"
range-parser: "npm:^1.2.1"
bin:
ezshare: index.js
languageName: unknown
Expand Down Expand Up @@ -1642,7 +1643,7 @@ __metadata:
languageName: node
linkType: hard

"range-parser@npm:~1.2.1":
"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1":
version: 1.2.1
resolution: "range-parser@npm:1.2.1"
checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0
Expand Down

0 comments on commit a877c3e

Please sign in to comment.