All I want to do is have a nice and simple function that'll take an url and save it to a file, however every single implementation me or some JS developer friends have been able to come up with throughout the day gives the same end result: an empty file.
import * as fs from 'fs';
import * as path from 'path';
import fetch from 'node-fetch';
import { Headers } from 'node-fetch';
export function downloadURL(url, saveLocation) {
const absSaveLocation = path.resolve(saveLocation);
const myHeaders = new Headers();
myHeaders.append('User-Agent', 'hifumi-js:v1.0.0');
if (url.includes("pximg")) {
myHeaders.append('Referer', 'https://www.pixiv.net/');
}
const requestOptions = {
method: 'GET',
headers: myHeaders,
}
const fileStream = fs.createWriteStream(absSaveLocation);
fetch(url, requestOptions)
.then(res => res.body.pipe(fileStream))
.catch(error => console.log('error', error));
fileStream.on('finish', () => {fileStream.close();});
}
I've tried a bunch of different libraries, including https, request, fetch, axios and all of them give me the same useless, empty file. It can't be the url as well since it's matched against a regex first before downloading and I've confirmed with countless different urls.
So I managed to fix this myself in the end by abandonding the whole idea of trying to use a stream to write to the file.
const fileStream = fs.createWriteStream(absSaveLocation);
fetch(url, requestOptions)
.then(res => res.body.pipe(fileStream))
.catch(error => console.log('error', error));
fileStream.on('finish', () => {fileStream.close();});
has now become
await fetch(url, requestOptions)
.then(response => response.arrayBuffer())
.then(buffer => fs.writeFile(absSaveLocation, new Uint8Array(buffer)))
.catch(error => console.log('error', error));