2016-10-26 5 views
1

Der folgende Code wird verwendet, um eine .zip Datei von unserer Webanwendung abzurufen. Die Datei wird erzeugt, indem eine andere Anwendung sicher geschlossen und dann gezippt wird, um sie schließlich zum Herunterladen zu senden.Rückruf bei rekursiver Funktion

var dl = function() { 
    request({ 
     method: 'GET', 
     uri: 'some_url', 
     headers: { 
      'User-Agent': 'Scripted-Download' 
     }, 
     encoding: null, 
     jar: true 
    }, function(err, res, body) { 
     if (err) throw(err) 
     if (res.headers['content-type'] === 'application/zip;charset=utf-8') { 
      process.stdout.write('\rDownloading file ..') 
      var id = uuid.v4() 
      , file = path.resolve(__dirname, '../../' + id + '.zip') 
      fs.writeFile(file, body, function(err) { 
       if (err) throw(err) 
       process.stdout.write('\rFile downloaded ' + id + '.zip') 
       process.exit(0) 
      }) 
     } else { 
      process.stdout.write('\rAwaiting file ..') 
      setTimeout(dl(), 30 * 1000) 
     } 
    }) 
} 

Dies funktioniert wie erwartet. Ich muss dies jedoch von einem anderen Skript aus verwenden. Also der obige Code gibt eine id der heruntergeladenen Datei, dann von einem anderen Skript kann ich die .zip extrahieren und die extrahierten Dateien in ein Verzeichnis mit der gleichen id. Diese Dateien würden dann zum Download bereitgestellt werden.

EDIT Im Grunde muss ich dieses Skript auszuführen, um den Inhalt zu extrahieren, wenn es dann mit res.render() eine Benutzeroberfläche heruntergeladen ist laden, wenn die beiden vorherigen Schritte abgeschlossen sind. Dies muss mit einer id durchgeführt werden, so dass zwei Benutzer keine in Konflikt stehenden Dateien erstellen.

+0

Was ist die Schwierigkeit, die Sie haben? Im Knoten in einen Ordner extrahieren, der mit 'http' versehen ist? – Pogrindis

+0

Ich muss wissen, dass die Datei heruntergeladen wurde. Andernfalls wird der Benutzer versuchen, eine Datei herunterzuladen, die nicht existiert, die eine 404 erzeugen würde. – MindVox

+0

Bitte sehen Sie meine ** EDIT ** – MindVox

Antwort

3

in den Kommentaren erwähnt soll, verspricht dies einfach machen. Stellen Sie zunächst die benötigte Async-Funktionalität fest:

function makeRequest(parameters) { 
    return new Promise(function (resolve, reject) { 
     request(parameters, function (err, res, body) { 
      if (err) { reject (err); } 
      else { resolve({ res: res, body: body }); } 
     }); 
    }); 
} 

function writeFile(file, body) { 
    return new Promise(function (resolve, reject) { 
     fs.writeFile(file, body, function(err) { 
      if (err) { reject(err); } 
      else { resolve(); } 
     }); 
    }); 
} 

function timeout(duration) { 
    return new Promise(function (resolve) { 
     setTimeout(resolve, duration); 
    }); 
} 

Dann verwenden Sie sie.

var dl = function() { 
    return makeRequest({ 
     method: 'GET', 
     uri: 'some_url', 
     headers: { 
      'User-Agent': 'Scripted-Download' 
     }, 
     encoding: null, 
     jar: true 
    }).then(function (result) { 
     if (result.res.headers['content-type'] === 'application/zip;charset=utf-8') { 
      process.stdout.write('\rDownloading file ..') 
      var id = uuid.v4() 
      , file = path.resolve(__dirname, '../../' + id + '.zip'); 

      return writeFile(file, result.body) 
       .then(function() { return id; }); 
     } else { 
      process.stdout.write('\rAwaiting file ..'); 

      return timeout(30 * 1000).then(dl); 
     } 
    }); 
} 

dl().then(function (id) { process.stdout.write('\rid is: ' + id); }); 
+0

Wo ist 'aspectDownload' definiert? – MindVox

+0

@KarlBateman Sie sagen mir. Sie haben es gerade 16 Minuten vor Ihrer eigenen Frage bearbeitet. Meine Antwort wurde aktualisiert, um dem aktuellen Status Ihrer Frage zu entsprechen. – JLRishe

+0

Ah, ja, ich dachte, das ist es, worauf es sich bezieht. Nach dem Kopieren Ihrer Antwort und dem Hinzufügen der richtigen URL erhalte ich den folgenden Fehler: "TypeError: first._onTimeout ist keine Funktion" – MindVox

0

Sie können eine asynchrone Dienstprogrammbibliothek wie async verwenden.

Das Muster, das Sie suchen, scheint das waterfall Muster zu sein. Dadurch können Sie die Daten, die Sie benötigen, von einer Aufgabe zur nächsten weitergeben.

function requestFile(cb){ 
    request({ 
     method: 'GET', 
     uri: 'some_url', 
     headers: { 
      'User-Agent': 'Scripted-Download' 
     }, 
     encoding: null, 
     jar: true 
    }, function(err, res, body) { 
     if (err) throw(err) 
     if (res.headers['content-type'] === 'application/zip;charset=utf-8') { 
      process.stdout.write('\rDownloading file ..'); 
      cb(null, body); 
     } 
     else{ 
      process.stdout.write('\rAwaiting file ..'); 
      setTimeout(requestFile, 30 * 1000) 
     } 
    }); 
} 


function saveFile(body, cb){ 
    var id = uuid.v4() 
     , file = path.resolve(__dirname, '../../' + id + '.zip') 
    fs.writeFile(file, body, function(err) { 
     if (err) throw(err) 
     process.stdout.write('\rFile downloaded ' + id + '.zip'); 
     cb(null, id); 
    }) 
} 

function render(id, cb) { 
    //do what ever you need with your id 
    cb(); 
} 

async.waterfall([ 
    requestFile, 
    saveFile, 
    render 
], function(err){ 

}); 

BTW, empfehle ich Ihnen die Daten direkt aus dem Server streamen auf der Festplatte, anstatt sie alle in einem Puffer zu sammeln und dann speichern.

Sie können data Zuhörer auf dem Request-Objekt erstellen und sie dann auf der Festplatte direkt streamen oder sogar request.pipe(file)

Beispiel verwenden nur: Wie

function streamFile(){ 

    var id = uuid.v4() 
     , file = path.resolve(__dirname, '../../' + id + '.zip'); 
    var stream = fs.createWriteStream(file); 
    stream.on('error', function(err){ 
     throw err; 
    }).on('close', function(){ 
     process.stdout.write('\rFile downloaded ' + id + '.zip') 
    }); 

    request({ 
     method: 'GET', 
     uri: 'some_url', 
     headers: { 
      'User-Agent': 'Scripted-Download' 
     }, 
     encoding: null, 
     jar: true 
    }).on('error', function(err) { 
     throw(err) 
    }).on('response', function(res){ 
     if (res.headers['content-type'] === 'application/zip;charset=utf-8') { 
      process.stdout.write('\rDownloading file ..'); 
      cb(null, body); 
     } 
     else{ 
      process.stdout.write('\rAwaiting file ..'); 
      res.destroy(); 
      setTimeout(streamFile, 30 * 1000) 
     } 
    }).pipe(stream); 
} 
+0

Ich werde es versuchen, danke. – MindVox

+0

Ich denke, das Problem hier ist die 'setTimeout()', weil ich keinen Wert von dieser Funktion oder einen Rückruf zurückgeben kann. – MindVox

+1

was ist 'aspectDownload' Funktion –