【问题标题】:Asynchronous issue while uploading multiple files上传多个文件时出现异步问题
【发布时间】:2018-02-01 04:03:17
【问题描述】:

您好我正在尝试上传多个文件,文件写入是正确的。但我想将文件移动到 mongo 网格 fs 中,第一个文件只是正确移动文件的其余部分没有移动到网格 fs 中,也没有取消链接。

这是我的代码:

for (var i = 0; i < files.length; i++) {
    (function(i) {
        var singleFile = files[i];
        var fileData = JSON.parse(files[i].name);
        var fileName = fileData.fileName;
        var fileType = files[i].type;
        var uniqId = fileData.attachmentId;
        var targetPath = "./attachments/" + uniqId;
        var tmp_path = files[i].path;

    console.log("uniqId : " + uniqId);
    //uploadFile(tmp_path,targetPath,fileName,uniqId,fileType);

    fs.readFile(tmp_path, function(err, data) {
        fs.writeFile(targetPath, data, function(err) {
            if (!err) {
                mongoose.connect(configSettings.mongodb.ip, configSettings.mongodb.databasename, configSettings.mongodb.port, function(err, succ) {
                    var id = new ObjectID(uniqId);
                    new GridStore(mongoose.connection.db, id, fileName, 'w', {
                        'content_type': 'application/octet-stream'
                    }).open(function(err, gs) {
                        gs.writeFile(targetPath, function(err) {
                            if (err) {
                                console.log("err");
                            }
                            gs.close(function(err) {
                                console.log("success");
                                fs.unlink("./attachments/" + uniqId, function(err) {
                                    console.log("err : " + err);
                                    console.log(uniqId + ' ::successfully deleted ');
                                });
                                mongoose.connection.close();
                            });
                        });
                    });
                });
            }
        });
    });
   })(i);
}

    res.send("success");

我尝试过使用闭包函数,即使我也尝试过创建单独的函数,但结果相同(仅插入和取消链接一个文件)。

在这种情况下,我必须做什么才能将所有文件存储在 gridfs 中并从临时文件夹中取消链接?

【问题讨论】:

  • mongodb 是否支持所有这些并发打开和关闭?不应该先建立与mongobd的连接并打开网格,然后在这个打开成功函数中,放置循环以启动所有文件处理吗?

标签: javascript node.js mongodb express gridfs


【解决方案1】:

这是我的猜测。由于您的调用被推迟到以后,您的函数结束并且文件列表可能被 Node 或其他任何东西删除,您可以在这里看到一个简化的示例:

let myList = [1, 2, 3, 4, 5];

function doWork(list) {
  console.log('Start of function');
  
  for (let i = 0; i < list.length; i++) {
    (function(i) {
      setTimeout(function() {
        console.log('Working on index', i);
        console.log('list[i] :', list[i]);
      }, 100);
    })(i);
  }

  console.log('End of function');
}

doWork(myList);

myList[4] = null;

解决方案是将文件(或列表/索引对)本身包含在您的上下文中以使其保持活动状态:

let myList = [1, 2, 3, 4, 5];

function doWork(list) {
  console.log('Start of function');
  
  for (let i = 0; i < list.length; i++) {
    (function(num) {
      setTimeout(function() {
        console.log('Num :', num);
      }, 100);
    })(list[i]);
  }

  console.log('End of function');
}

doWork(myList);

myList[4] = null;

【讨论】:

    【解决方案2】:

    实际上问题出在 gridFs 连接上,文件在循环内上传,网格连接已启动并写入第一个文件,循环继续并行。一旦从gridfs打开连接,它应该在插入另一个文件之前关闭,并且必须正确重新连接下一次。

    这是工作代码检查它:

    var files = req.files.fileData[0];
    var count = "";
    
    if(files instanceof Array){
        count = files.length;
    }
    else{
        count = 1;
    }
    
    if(!fs.existsSync('./attachments')){
        console.log("Creating the attachments folder.");
        fs.mkdir('./attachments');
    }   
    
    function moveToGrid(gridArr,callback){      
        var uniqId = gridArr.uniqId, 
            filePath = gridArr.targetPath, 
            fileName = gridArr.fileName,
            fileType = gridArr.fileType;
    
            console.log(filePath+' '+fileName+' '+fileType + ' '+uniqId);
    
        mongoose.connect(configSettings.mongodb.ip, configSettings.mongodb.databasename, configSettings.mongodb.port, function (err, succ){
    
            var uploadResponse   = function(uniqId){
                // Delete the tmp file
                fs.unlink("./attachments/" + uniqId, function (err) {
                    console.log(uniqId + ' ::temp file successfully deleted ');
                });
                 mongoose.connection.close();
                 console.log("=========request END time==========::::" + (new Date()).toString() + "::" +(new Date()).getMilliseconds() );
                 callback();
            };
            var id = new ObjectID(uniqId);
            new GridStore(mongoose.connection.db,id,fileName, 'w',{'content_type':'application/octet-stream'}).open(function(err, gs) {
                gs.writeFile(filePath, function(err) {
                    if(err){
                    console.log("err : "+err);
                    }
                    gs.close(function(err) {
                        uploadResponse(uniqId);
                    });
                });
            });
        });
    }
    
    var recursive = function(gridArr){  
        function uploader(i){
          if( i < gridArr.length ){
            moveToGrid(gridArr[i],
                 function(){
                  uploader(i+1)
                 });
           }
           else{
            res.send("success");
           }
        }
        uploader(0); 
    }
    
    if(count > 1){
        var gridArr = [];
        for(var i=0; i<files.length; i++){
            (function(i){
                var singleFile = files[i];
                    var fileData = JSON.parse(singleFile.name);
                    var fileName = fileData.fileName;
                    var fileType = singleFile.type;
                    var uniqId   =  fileData.attachmentId;
                    var targetPath =  "./attachments/" + uniqId;
                    var tmp_path = singleFile.path;
    
                    fs.readFile(tmp_path,function(err,data){
                        fs.writeFile(targetPath,data,function(err){
                            if(!err){
                                gridArr.push({"uniqId":uniqId, "targetPath":targetPath, "fileName":fileName, "fileType":fileType});
                                count --;
                                if(count == 0){
                                    recursive(gridArr);
                                }
                            }
                        });
                    });
            }(i));                  
        }
    }
    else{
        var gridArr = [];
        var singleFile = files;
        var fileData = JSON.parse(singleFile.name);
        var fileName = fileData.fileName;
        var fileType = singleFile.type;
        var uniqId   =  fileData.attachmentId;
        var targetPath =  "./attachments/" + uniqId;
        var tmp_path = singleFile.path;
    
        fs.readFile(tmp_path,function(err,data){
            fs.writeFile(targetPath,data,function(err){
                if(!err){
                    gridArr.push({"uniqId":uniqId, "targetPath":targetPath, "fileName":fileName, "fileType":fileType});
                    count --;
                    if(count == 0){
                        recursive(gridArr);
                    }
                }
            });
        });     
    }
    

    使用此代码,我们可以将多个文件插入到 mongo gridFs.. 希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      简短的回答在这里学习如何在循环中异步函数

      (function loop(i) {
      if(i==4) return
      setTimeout(function() {
        console.log('Working on index', i);
        loop(++i)
       }, 1000);
      })(0);
      

      TL;DR https://mongodb.github.io/node-mongodb-native/api-generated/gridstore.html

      【讨论】:

        猜你喜欢
        • 2019-02-13
        • 1970-01-01
        • 2014-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-13
        • 1970-01-01
        相关资源
        最近更新 更多