2016-10-26 12 views
1

Следующий код используется для извлечения файла .zip из нашего веб-приложения. Файл создается путем безопасного закрытия другого приложения, затем с помощью zipping, наконец, отправляя его для загрузки.Обратный вызов для рекурсивной функции

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) 
     } 
    }) 
} 

Это работает должным образом. Однако мне нужно использовать это из другого скрипта. Таким образом, приведенный выше код возвращает id загруженного файла, затем из другого сценария я могу извлечь .zip и поместить извлеченные файлы в каталог с тем же id. Эти файлы затем будут доступны для загрузки.

EDIT По существу я должен выполнить этот сценарий, извлечь содержимое, когда он загружен затем загрузить пользовательский интерфейс с res.render(), когда предыдущие два шага завершены. Это необходимо сделать с помощью id, чтобы два пользователя не создавали конфликтующие файлы.

+0

В чем вы испытываете трудности? Извлечь в узел в папку, подверженную «http»? – Pogrindis

+0

Мне нужно знать, что файл был загружен. В противном случае пользователь будет пытаться загрузить файл, который не существует, который будет производить 404. – MindVox

+0

Пожалуйста, см. Мой ** EDIT ** – MindVox

ответ

3

Как уже упоминалось в комментариях, обещания должны сделать это легко. Прежде всего, вы должны прокомментировать необходимые функции асинхронизации:

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); 
    }); 
} 

Затем используйте их.

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

Где находится 'aspectDownload'? – MindVox

+0

@KarlBateman Ты мне скажи. Вы только что отредактировали его из своего вопроса 16 месяцев назад. Обновлен мой ответ, чтобы соответствовать текущему состоянию вашего вопроса. – JLRishe

+0

А, да, я думал, это то, о чем он говорил. После копирования вашего ответа и добавления правильного URL-адреса я получаю следующую ошибку: TypeError: first._onTimeout не является функцией – MindVox

0

Вы можете использовать библиотеку утилиты async, такую ​​как async.

Образец, который вы ищете, представляет собой шаблон waterfall. Это позволит вам передавать нужные данные из одной задачи в другую.

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, я рекомендую вам поток данных с сервера прямо на диск, а не собирать все это в буфере, а затем сохранить его.

Вы можете создать data слушателей на объект запроса, а затем поток их непосредственно на диск или даже просто использовать request.pipe(file)

Пример:

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

Я дам вам попробовать, спасибо. – MindVox

+0

Я думаю, проблема здесь в 'setTimeout()', потому что я не могу вернуть значение из этой функции или использовать обратный вызов. – MindVox

+1

Что такое функция 'aspectDownload' –

 Смежные вопросы

  • Нет связанных вопросов^_^