skip to Main Content

I am trying to download a zip from my Apache server using NodeJS. When I try to download the zip, it downloads about 500KB of the 8MB of the zip and then just stops downloading it. The NodeJS process stays online for about a minute and then dies with the error read ETIMEDOUT. When I try to download the same zip through the same endpoint by using my browser, it downloads it without any problem. I’ve tried to download the zip using the NodeJS script with several servers ruling out any network issue. The NodeJS script I’m using is as follows:

const axios = require('axios').default;
const path = require('path');
const fs = require('fs');

axios.get('https://example.org/endpoint.php').then(res => {
    fs.writeFileSync(path.join(__dirname, `./file.zip`), res.data);
}).catch(console.log);

The endpoint is written in PHP as follows:

$zipPath = "/path/to/zip";

$filesize = filesize($zipPath);

header('Content-Description: File Transfer');
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="file.zip"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $filesize);

flush();

readfile($zipPath);
exit();

The endpoint doesn’t send the Content-Length header in the response, which I don’t quite understand. I have read somewhere that this might cause the NodeJS script being unable to fully download the zip, but I’m not quite sure if this is correct. I’ve tried to check whether it is the $filesize variable causing the issue by changing the header name to X-Content-Length, which gave me the correct output, ruling out the variable being the cause. I’ve also read somewhere that the header Transfer-Encoding: chunked prevents me from setting the Content-Length header. I’ve tried several solutions which helped for others, but these didn’t work for me. These are the headers the download endpoint sends:

HTTP/1.1 200 OK
Date: Wed, 24 Apr 2024 11:37:13 GMT
Server: Apache/2.4.52 (Ubuntu)
Content-Description: File Transfer
Content-Disposition: attachment; filename="file.zip"
Content-Transfer-Encoding: binary
Connection: Keep-Alive, Keep-Alive
Expires: 0
Cache-Control: must-revalidate, post-check=0, pre-check=0
Pragma: public
Upgrade: h2,h2c
Connection: Upgrade
Keep-Alive: timeout=5, max=100
Transfer-Encoding: chunked
Content-Type: application/zip

Any help would be really appreciated. Thanks.

2

Answers


  1. Chosen as BEST ANSWER

    It eventually appeared to be a firewall issue.


  2. You need to pipe the response into the fileStream.

    try below:

    const axios = require('axios').default;
    const path = require('path');
    const fs = require('fs');
    
    axios.get('https://example.org/endpoint.php')
    .then(res => {
        res.pipe(
            fs.openSync(path.join(__dirname, `./file.zip`)
              .createWriteStream()
        )
    })
    .catch(console.log);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search