2013-06-12 34 views
2

我正在上傳圖像網址的數組以保存到S3。代碼有效,但不會異步執行。給控制檯打上時間標記似乎表明首先所有圖像都被提取並緩衝,然後它們被順序保存到s3。我跑了100張圖片,第一張圖片沒有提交給s3,直到第100張被提取。至少它看起來像這樣,因爲我從圖像請求回調中獲得了控制檯中的時間戳流,並且直到最後一次圖像回調已經加了時間戳纔會啓動「保存到s3」時間戳。我對節點相當陌生,在經過兩天的實驗後,我還沒有破解這個。如何使用node.js獲取圖像URL數組並異步保存到s3?

我也試過直接調出它,但那需要所有文件都有內容長度設置,有些不會。我原本在一個函數中使用了getImageFromUrl,但將其分解爲三個單獨的小函數,以幫助找出問題所在。我正在使用request,對於s3使用knox,對於async.each迭代器使用caolan的異步庫。代碼如下:

var images2get = req.body.images2get; // an array of image urls to be fetched and saved to s3 
var startTime = (new Date()).getTime(); 

//iterate over the array and get each image, save to S3 
var imageNumber = 0; // this needs to come before the iterator so it's defined 

    async.each(images2get, getImageFromUrl, function(err){ 
     if(err) { 
      console.log('async each failed for images2get'); 
     } else { 
      res.send(200); 
     } 
    }); 

function getImageFromUrl(url2fetch, nextImage){ 
    var options = {encoding: null, 
        url: url2fetch, 
        method: 'GET', 
        timeout: 10*1000 
        } 
    request(options, function(err, fetchResponse, body){ 
     if(!err && fetchResponse && fetchResponse.statusCode == 200) { 
      nextImage(); //we've got the image, call the iterator to fetch the next one 
      var s3Config = prepareImageForS3(fetchResponse, url2fetch); 
      saveToS3(body, s3Config); 
     } else { 
     //there was a problem fetching the url 
     console.log('Error ' + fetchResponse.statusCode + ' Failed to get image from ', url2fetch.absolute); 
     nextImage(); 
     }  
    }); 
}; 

function prepareImageForS3(fetchResponse, url2fetch) { 
    console.log('preparing image ' + imageNumber + ' at ', (Date.now() - startTime)); 
    imageNumber += 1; 
    var filename = '/' + userId + '/' + pageId + '/image' + imageNumber; 
    var headers = { 
     'Content-Type': fetchResponse.headers['content-type'], 
     'x-amz-acl': 'public-read' 
    }; 
    return{ 
     'filename': filename, 
     'filetype': 'image', 
     'filenumber': imageNumber, 
     'headers': headers, 
     'replaceSrc': true, 
     'url': url2fetch 
    }; 
}; 

function saveToS3(file, s3Config) { 
    s3Client.putBuffer(file, s3Config.filename, s3Config.headers, function(err, res){ 
     console.log('image ' + imageNumber + ' submitting to s3 at ', (Date.now() - startTime)); 
     //console.log('response from s3 save from url, status:', res.statusCode, 'url:', res.req.url); 
     if(!err && res.statusCode === 200 && s3Config.replaceSrc) { 
      console.log('image ' + imageNumber + ' saved to s3 at ', (Date.now() - startTime)); 
     } else { 
      console.log('failed to save image to S3 from ' + res.req.url) 
     }  
    }); 
}; 

回答

0

有幾件事情,你可以用你的代碼改善:

  • HTTP代理

首先,Node.js的使用了HTTP Agent,這限制了與主機的併發連接數量。如果不是這樣,您可能會意外地通過數千個連接敲擊網站。

您可以通過傳遞{agent: false}來禁用它。請注意,knox already disables it

我懷疑這是你的代碼順序運行的原因。

  • Async.each

Async.each將並行運行所有的迭代。當你打電話給nextImage()時,你不會說異步開始下一次迭代,而是說你已經完成了。所有迭代完成後,異步完成。這裏的問題是在你告訴異步你完成之後繼續工作。

相關問題