mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-07 09:51:37 +00:00
Fix slow downloads: larger buffers, Content-Length headers, parallel streams
This commit is contained in:
parent
c010f0e1eb
commit
cf0a432027
3 changed files with 22 additions and 4 deletions
|
|
@ -184,6 +184,11 @@ class LibraryItemController {
|
||||||
if (audioMimeType) {
|
if (audioMimeType) {
|
||||||
res.setHeader('Content-Type', audioMimeType)
|
res.setHeader('Content-Type', audioMimeType)
|
||||||
}
|
}
|
||||||
|
// Set Content-Length so clients can show accurate progress bars.
|
||||||
|
const fileStat = await fs.stat(libraryItemPath).catch(() => null)
|
||||||
|
if (fileStat) {
|
||||||
|
res.setHeader('Content-Length', fileStat.size)
|
||||||
|
}
|
||||||
await new Promise((resolve, reject) => res.download(libraryItemPath, req.libraryItem.relPath, (error) => (error ? reject(error) : resolve())))
|
await new Promise((resolve, reject) => res.download(libraryItemPath, req.libraryItem.relPath, (error) => (error ? reject(error) : resolve())))
|
||||||
} else {
|
} else {
|
||||||
const filename = `${itemTitle}.zip`
|
const filename = `${itemTitle}.zip`
|
||||||
|
|
@ -1097,6 +1102,12 @@ class LibraryItemController {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Set Content-Length so clients (including the Android app) can show accurate
|
||||||
|
// download progress and avoid chunked-transfer encoding when the file size is known.
|
||||||
|
const fileStat = await fs.stat(libraryFile.metadata.path).catch(() => null)
|
||||||
|
if (fileStat) {
|
||||||
|
res.setHeader('Content-Length', fileStat.size)
|
||||||
|
}
|
||||||
await new Promise((resolve, reject) => res.download(libraryFile.metadata.path, libraryFile.metadata.filename, (error) => (error ? reject(error) : resolve())))
|
await new Promise((resolve, reject) => res.download(libraryFile.metadata.path, libraryFile.metadata.filename, (error) => (error ? reject(error) : resolve())))
|
||||||
Logger.info(`[LibraryItemController] Downloaded file "${libraryFile.metadata.path}"`)
|
Logger.info(`[LibraryItemController] Downloaded file "${libraryFile.metadata.path}"`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -318,8 +318,9 @@ module.exports.downloadFile = (url, filepath, contentTypeFilter = null) => {
|
||||||
const totalSize = parseInt(response.headers['content-length'], 10)
|
const totalSize = parseInt(response.headers['content-length'], 10)
|
||||||
let downloadedSize = 0
|
let downloadedSize = 0
|
||||||
|
|
||||||
// Write to filepath
|
// Use a 512 KiB write buffer. Node's default 16 KiB highWaterMark causes
|
||||||
const writer = fs.createWriteStream(filepath)
|
// many small write syscalls for large audio files and limits throughput.
|
||||||
|
const writer = fs.createWriteStream(filepath, { highWaterMark: 524288 })
|
||||||
response.data.pipe(writer)
|
response.data.pipe(writer)
|
||||||
|
|
||||||
let lastProgress = 0
|
let lastProgress = 0
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,11 @@ module.exports.zipDirectoryPipe = (path, filename, res) => {
|
||||||
res.attachment(filename)
|
res.attachment(filename)
|
||||||
|
|
||||||
const archive = archiver('zip', {
|
const archive = archiver('zip', {
|
||||||
zlib: { level: 0 } // Sets the compression level.
|
zlib: { level: 0 }, // Sets the compression level (0 = store, no CPU overhead).
|
||||||
|
// Increase the internal pipeline highWaterMark from 16 KiB to 512 KiB.
|
||||||
|
// This allows archiver to buffer more data before applying backpressure,
|
||||||
|
// keeping the read-from-disk and write-to-network pipelines busy.
|
||||||
|
highWaterMark: 524288
|
||||||
})
|
})
|
||||||
|
|
||||||
// listen for all archive data to be written
|
// listen for all archive data to be written
|
||||||
|
|
@ -67,7 +71,9 @@ module.exports.zipDirectoriesPipe = (pathObjects, filename, res) => {
|
||||||
res.attachment(filename)
|
res.attachment(filename)
|
||||||
|
|
||||||
const archive = archiver('zip', {
|
const archive = archiver('zip', {
|
||||||
zlib: { level: 0 } // Sets the compression level.
|
zlib: { level: 0 }, // Sets the compression level (0 = store, no CPU overhead).
|
||||||
|
// Increase the internal pipeline highWaterMark from 16 KiB to 512 KiB.
|
||||||
|
highWaterMark: 524288
|
||||||
})
|
})
|
||||||
|
|
||||||
// listen for all archive data to be written
|
// listen for all archive data to be written
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue