0

I'm having an issue with express app. I'm using multer to upload a file, then using res.download to send the file back. This seems to work with text files but images are not working. When I send the file to the client, the file size is actually a little bit smaller than what is on the server. It seems as is the full file isn't being transferred.

I'm not doing anything fancy with the response I'm just using res.download. I've researched basically every article I can find and it seems like this works for everyone else.

Only text files are working. Word, excel, pdfs are all saying they're corrupted when downloaded.

EDIT: Here is the function that runs res.download. Its passed the file path, mimetype etc.

function downloadFile(req, res) {   
    let fpath = req.body.path; 
    let originalName = req.body.originalName;
    let mimetype = req.body.mimetype;
    let filename = req.body.filename;

    res.download(fpath, originalName, function(err) {
        if (err) {
            console.log(err);
        }        
    });

}

EDIT: Here is my redux thunk that makes the request and triggers the file download. The download function comes from the downloadjs library.

export const downloadFile = (path, originalName, mimetype, filename) => { 
    return dispatch => {                
        return axios.post('/api/v1/quotes/downloadFile', { path: path, originalName: originalName, mimetype: mimetype, filename: filename })
        .then(res => {                
            if (res.status !== 200) {
                ErrorHandler.logError(res);                
            } 
            else {                                        
               // download(res.data, originalName);             
               download(new Blob([res.data]), originalName, mimetype);
            }         
        }).catch(function(error) {
            ErrorHandler.logError(error);                               
        });
    }
}

EDIT: Here is a small sample of what I see in the network tab. It seems like its the image contents, but the size is smaller than what is on the server and when I try to open it I get an unsupported file type error.

PNG


IHDR{>õIÖÕsRGB®ÎégAMA±üa    pHYsÃÃÇo¨d+{IDATx^íÝml\×ßq¾jº]´Mv´¤ÛÅvÛnÛEßt4/vQ[äÅ¢¯òb>-
él²æJv$Ǧ(ѦDÉR$R
¥V-Q6mÅ4kF¶®,U%ÊYS¶åDr¼5ÿ=ÿ{Ï9sîÌ!Gßp@Î}¾çÞ9÷7÷Þ¹Ó!¸o/ÛÚaï>MOJ4µ¸aíÐF{÷ég?ùó?µÚa a=öFØHa a=öFØHa 

Request Header

Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 160
Content-Type: application/json;charset=UTF-8
Host: localhost:3000
Origin: http://localhost:3000
Referer: http://localhost:3000/Quote
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36

Response Header

accept-ranges: bytes
cache-control: public, max-age=0
connection: close
content-disposition: attachment; filename="sSubLineConfigIds.PNG"
content-length: 11238
content-type: application/octet-stream
date: Wed, 17 Jul 2019 19:03:54 GMT
etag: W/"2be6-16c0151b84a"
last-modified: Wed, 17 Jul 2019 19:03:48 GMT
x-powered-by: Express
RT Admin
  • 19
  • 6

2 Answers2

1

I was able to figure this out. What I ended up doing is converting the file into base64 and setting the download link to that base64 string.

The node function that gets hit to build the base64 string.

function downloadFile(req, res) {   
    let fpath = req.body.path;   
    let mimetype = req.body.mimetype; 

    fs.readFile(fpath, function (err, data) {        
        if (err) res.status(500).send('File could not be downloaded');

        var base64 = Buffer.from(data).toString('base64');
        base64='data:' + mimetype + ';base64,'+base64;
        res.send(base64);
    });  
}

Here is the client side code that builds a link, simulates click, and sets the source link equal to the base64 string.

export const downloadFile = (path, originalName, mimetype, filename) => { 
    return dispatch => {                
        return axios.post('/api/v1/quotes/downloadFile', { path: path, originalName: originalName, mimetype: mimetype, filename: filename })
        .then(res => {                
            if (res.status !== 200) {
                ErrorHandler.logError(res);                
            } 
            else {                        
                const linkSource = res.data;
                const downloadLink = document.createElement("a");
                const fileName = originalName;

                downloadLink.href = linkSource;
                downloadLink.download = fileName;
                downloadLink.click();                        
            }         
        }).catch(function(error) {
            ErrorHandler.logError(error);                               
        });
    }
}
RT Admin
  • 19
  • 6
0

Things looks fine as per the code shared. It seems this request is initiated through XHR from your front end side than you have to write the download logic to convert the response to blob and then create a file for download as mentioned how-to-create-a-dynamic-file-link-for-download-in-javascript

  • I will give this a shot. I will edit the post with this info, but in my redux action I'm actually using downloadjs to download the file. I'll put the code up above. – RT Admin Jul 17 '19 at 19:49
  • It seems like that code is more focused on how to get the file to download which isn't really my issue. I can trigger the download using the downloadjs library but the files just can't be opened afterwards without an error. – RT Admin Jul 17 '19 at 21:01