2015-09-07 15 views
5

Vorrei scaricare i file con il mio browser dal mio server in esecuzione con NodeJS. Sul lato server, per servire il file che ho: esisteScaricare un file dal server Node.JS con AngularJS

exports.download = function(req, res) { 
    var filename = "33.jpg"; 
    var filePath = path.join(__dirname, '..', '..', 'downloads', filename); 
    var stat = fs.statSync(filePath); 

    var fileToSend = fs.readFileSync(filePath); 

    res.writeHead(200, { 
     'Content-Type': 'image/jpeg', 
     'Content-Length': stat.size, 
     'Content-Disposition': filename 
    }); 
    res.end(fileToSend); 
}; 

Il file chiamato 33.jpg ed è 744KB dimensioni. La chiamata da parte del cliente grandi opere

Sul lato client con AngularJS ecco come lo chiamo una chiamata post per ottenere il file (attualmente il parametro URI non viene utilizzato):

$scope.downloadTrack = function(uri) { 
    $http.post('/api/files/download', {uri: uri}).then(function(response) { 
    var blob = new Blob([response.data], { type: 'image/jpeg' }); 
    var fileName = response.headers('content-disposition'); 
    saveAs(blob, fileName); 
    }, function(response) { 
    console.log('Download error'); 
    console.log(response); 
    }); 
} 

Le intestazioni sono ok (posso recuperare il nome del file)

Il mio problema è che un file viene scaricato ma con una dimensione di 1,5 Mb ed è illeggibile. Ho provato diversi metodi con i flussi, aggiungere dati alla risposta, pipe, ecc. Senza successo. Un altro punto (non sono sicuro è importante): all'interno di Safari i file si apre con un'icona rotta visualizzata, all'interno di Chrome il file viene salvato

PS: ho creato il progetto con Yeoman se l'informazione è utile

Grazie tutto

[Update] Nuova versione di funzione di server (ancora non funziona)

exports.download = function(req, res) { 
    var filename = "33.jpg"; 
    var filePath = path.join(__dirname, '..', '..', 'downloads', filename); 
    var stat = fs.statSync(filePath); 
    var fileToSend = fs.readFileSync(filePath); 
    res.set('Content-Type', 'image/jpeg'); 
    res.set('Content-Length', stat.size); 
    res.set('Content-Disposition', filename); 
    res.send(fileToSend); 
}; 

[Update 2] Il file di dimensioni doppie contiene extra "efbffd" sequenza di char in modo casuale nel file rendendolo illeggibile

+0

'res.write (filedainviare); ris .end(); ' – AdityaParab

+0

Stesso risultato. Immagino che il problema derivi dal metodo Angular più del lato Node.JS ... –

risposta

6

Problema risolto con una definizione del tipo di risposta impostato blob

$http({ 
     url: '/api/files/download', 
     method: "POST", 
     data: { 
     uri: uri 
     }, 
     responseType: 'blob' 
    }).success(function (data, status, headers, config) { 
     var blob = new Blob([data], { type: 'audio/mpeg' }); 
     var fileName = headers('content-disposition'); 
     saveAs(blob, fileName); 
    }).error(function (data, status, headers, config) { 
    console.log('Unable to download the file') 
    }); 
+0

Errore: saveAs non è definito nella mia console. come risolvere –

+1

installare il modulo angular-file-saver e inserire SaveAs factory come parametro sul controller –

0

Stai inviando il capo della risposta, ma non il corpo utilizzando res#end invece di res#send (con una S).

exports.download = function(req, res) { 
    // ... 
    res.send(fileToSend); 
}; 

Dal Express documentation per res#end:

Use to quickly end the response without any data. If you need to respond with data, instead use methods such as res.send() and res.json().

+0

Grazie. Ho corretto (anche la parte delle intestazioni set) ma il risultato è lo stesso: un file ricevuto due volte più grande dell'originale e illeggibile dal browser (e os) –