Files
standardnotes-app-web/packages/desktop/app/javascripts/Main/FileBackups/FileDownloader.ts
2022-06-07 11:52:15 -05:00

55 lines
1.5 KiB
TypeScript

import { WriteStream, createWriteStream } from 'fs'
import { downloadData } from './FileNetworking'
export class FileDownloader {
writeStream: WriteStream
constructor(private chunkSizes: number[], private valetToken: string, private url: string, filePath: string) {
this.writeStream = createWriteStream(filePath, { flags: 'a' })
}
public async run(): Promise<'success' | 'failed'> {
const result = await this.downloadChunk(0, 0)
this.writeStream.close()
return result
}
private async downloadChunk(chunkIndex = 0, contentRangeStart: number): Promise<'success' | 'failed'> {
const pullChunkSize = this.chunkSizes[chunkIndex]
const headers = {
'x-valet-token': this.valetToken,
'x-chunk-size': pullChunkSize.toString(),
range: `bytes=${contentRangeStart}-`,
}
const response = await downloadData(this.writeStream, this.url, headers)
if (!String(response.status).startsWith('2')) {
return 'failed'
}
const contentRangeHeader = response.headers['content-range'] as string
if (!contentRangeHeader) {
return 'failed'
}
const matches = contentRangeHeader.match(/(^[a-zA-Z][\w]*)\s+(\d+)\s?-\s?(\d+)?\s?\/?\s?(\d+|\*)?/)
if (!matches || matches.length !== 5) {
return 'failed'
}
const rangeStart = +matches[2]
const rangeEnd = +matches[3]
const totalSize = +matches[4]
if (rangeEnd < totalSize - 1) {
return this.downloadChunk(++chunkIndex, rangeStart + pullChunkSize)
}
return 'success'
}
}