2014-01-08 66 views
1

我有一個簡單的node.js應用程序,用於監視新PDF文件的目錄。當它看到它們出現時,將它們FTP出來並將它們移動到另一個目錄。等待文件完成複製後再對其執行操作?

我遇到的問題是,如果文件碰巧有點大(例如10MB),我的應用程序在完成複製到目錄之前開始處理文件。

複製發生在網絡上,這樣可以減慢一些事情的速度。我需要一種方式來告訴我的應用程序等待文件完成複製後再處理它。

這樣做的最好方法是什麼?我試過了'grow-file'模塊,但它似乎不起作用,看起來開發人員已經放棄了它。

在此先感謝您的幫助。

+0

的Eh。將文件複製到同一文件系統上的臨時位置,然後將其移動到「待處理」目錄中。該文件將在任何體面的操作系統上一次全部移動。 – cHao

+0

如何在傳輸完成後將文件發送爲「xyz.inprogress」並將其重命名爲「xyz.pdf」? –

+0

請參閱http://stackoverflow.com/a/7242053/41576和http://stackoverflow.com/questions/13582827/how-to-check-in-node-js-if-a-file-is-open-正在寫入 –

回答

0

我有幾乎相同的問題,我需要在播放它們之前下載文件。我最終編寫了這個代碼,您可以輕鬆地爲您的操作重寫。

編輯:其實,你幾乎可以使用代碼,如果只是要小心下載的回調。

它利用回調逐個下載每個文件(我有帶寬問題),但是我有一個以前的版本,它開始全部下載,然後等待所有文件在回調之前在磁盤上。

如果你想使用它,你需要一個名爲DOWNLOAD_DIR的全局變量,它包含下載目錄的完整路徑。

你還需要http,但我認爲你已經擁有它了。

var http = require('http'); 

/*download 
IN_: file_url 
     string 
     url of the file to download 
    callback 
COM: Download the specified file to DOWNLOAD_DIR/name_of_the_file, and callback the full path to the file 
    callback null on error. 
*/ 
function download(file_url, callback) { 
    var options = { 
     host: url.parse(file_url).host, 
     port: 80, 
     path: url.parse(file_url).pathname 
    }, 
     file_name = url.parse(file_url).pathname.split('/').pop(), 
    //Creating the file 
     file = fs.createWriteStream(DOWNLOAD_DIR + file_name, {flags: 'w', encoding: 'binary'}), 
    console.log('Downloading file from ' + file_url); 
    console.log(LOG, '\tto ' + file_name); 
    http.get(options, function (res) { 
     res.pipe(file, {end: 'false'}); 
     //When the file is complete 
     res.on('end', function() { 
      //Closing the file 
      file.end(); 
      console.log(LOG, '\t\tDownloaded '+ file_name); 
      callback(DOWNLOAD_DIR + file_name); 
     }); 
    }); 

    process.on('uncaughtException', function(err) { 
     console.log('Can t download ' + file_url + '\t(' + err + ')'); 
     callback(null); 
    }); 

} 

/*download_all 
IN_: list 
     array of string 
     Names of the files to download 
    callback 
COM: Download all the file one after another 
*/ 
function download_all(list, callback) { 
    var i = 0, 
     fe; 

    function follow() { 
     //If there is download to do 
     if (i < list.length) { 
      //Checking if the file already exist 
      fe = fs.existsSync(DOWNLOAD_DIR + list[i].substr(list[i].lastIndexOf('/'))); 
      console.log('Checking ' + list[i]); 
      if (!fe) { 
       console.log('\tDo not exist'); 
       //If it doesn t, downloading it 
       download(list[i], function() { 
        i = i + 1; 
        //And go to the next file 
        follow(); 
       }); 
      } else { 
       //If it does, go to the next file 
       console.log('\tExist'); 
       i = i + 1; 
       follow(); 
      } 
     } else { 
      //When all files are downloaded 
      console.log('end'); 
      callback(); 
     } 
    } 
    follow(); 
} 

注意,在生產代碼,你應該fs.exist +回調

編輯替換fs.existSync(在下載):下面的代碼爲火全在一次下載。請注意,這是我編輯過的舊代碼。

請注意,此代碼是舊的,我沒有太多測試,並且也使用fs.existSync(這又對生產代碼不利)。

最後注意,如果下載失敗,下載的回調函數將會有null參數,那麼您將必須自行檢查。

/*download_all 
IN_: list 
     array of string 
     Names of the files to download 
    callback 
COM: Download all-at-once 
*/ 
function download_all(list, callback){ 
    var i=0, dltd, dlcp=0; 
    dltd=list.length; 

    function afterDownload(){ 
     dlcp=dlcp+1; 
     console.log("Telechargement fini:"+dlcp); 
     if(dlcp===dltd){ 
      callback(); 
     } 
    } 

    while(i<list.length) 
    { 
     if(!fs.existsSync(DOWNLOAD_DIR + list[i].substr(list[i].lastIndexOf('/')))) 
     { 
      //If the file do not exist 
      download(list[i], afterDownload); 
     } else { 
      afterDownload(); 
     } 
     i=i+1; 
    } 
} 

實施例:

var http = require('http'), 
    DOWNLOAD_DIR = '/home/user/download/', 
    list = ['http://somewebsite.com/video.mp4', 'http://somewebsite.com/video2.mp4', 'http://othersite.com/image.png']; 

download_all(list, function(){ 
    //Do stuff 
}); 
+0

如果您有多個需要下載的文件並在觸發不同功能之前檢查它們是否已完成,那麼該如何處理? –

+0

這就是它在做什麼。然而,這是一個古老的答案,使用已有的舊技術。您應該使用流量控制庫,比如'async',或者更好的是'Promise'來做到這一點。你想讓我更新我的答案嗎? – DrakaSAN

+0

謝謝你的回覆。其實我也有類似的問題。 我首先將圖像下載到一個文件夾(我不知道它們何時完成),然後壓縮該文件夾。因爲我有多個圖像需要多次調用下載圖像功能,這會增加複雜性。 http://stackoverflow.com/questions/40924340/how-to-trigger-a-function-after-all-the-downloads-are-finished –