Files
standardnotes-app-web/packages/desktop/app/javascripts/Main/FileBackups/FileDownloader.ts
Mo 4a29e2a24c chore: upgrade eslint and prettier (#2376)
* chore: upgrade eslint and prettier

* chore: add restrict-template-expressions
2023-07-27 14:36:05 -05:00

60 lines
1.5 KiB
TypeScript

import { createWriteStream, WriteStream } 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'
}
}