0

我在将第二个音频文件写入 gridfs 时遇到问题。我正在使用 ng-file-upload 来选择一个文件,将文件/二进制数据传递给 gridfs,然后将其写入数据库。第一个文件工作正常,但是除非我先加载不同的视图,然后返回我的音频视图/模板页面,否则我每次都会收到此错误:

TypeError: path must be a string
    at TypeError (native)
    at Object.fs.open (fs.js:540:11)
    at ReadStream.open (fs.js:1673:6)
    at new ReadStream (fs.js:1660:10)
    at Object.fs.createReadStream (fs.js:1608:10)
    at NativeConnection.<anonymous> (Z:\techFilez\webApp\MyPiCloud\routes\IO\writeFile.js:42:29)
    at NativeConnection.g (events.js:260:16)
    at emitNone (events.js:67:13)
    at NativeConnection.emit (events.js:166:7)
    at open (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:518:11)
    at NativeConnection.Connection.onOpen (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:527:5)
    at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:487:11
    at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\drivers\node-mongodb-native\connection.js:71:5
    at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\db.js:232:5
    at connectHandler (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\server.js:333:7)
    at g (events.js:260:16)
Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\server.js:336
      process.nextTick(function() { throw err; })
                                    ^

TypeError: path must be a string
    at TypeError (native)
    at Object.fs.open (fs.js:540:11)
    at ReadStream.open (fs.js:1673:6)
    at new ReadStream (fs.js:1660:10)
    at Object.fs.createReadStream (fs.js:1608:10)
    at NativeConnection.<anonymous> (Z:\techFilez\webApp\MyPiCloud\routes\IO\writeFile.js:42:29)
    at NativeConnection.g (events.js:260:16)
    at emitNone (events.js:67:13)
    at NativeConnection.emit (events.js:166:7)
    at open (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:518:11)
    at NativeConnection.Connection.onOpen (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:527:5)
    at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\connection.js:487:11
    at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\lib\drivers\node-mongodb-native\connection.js:71:5
    at Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\db.js:232:5
    at connectHandler (Z:\techFilez\webApp\MyPiCloud\node_modules\mongoose\node_modules\mongodb\lib\server.js:333:7)
    at g (events.js:260:16)
 [nodemon] app crashed - waiting for file changes before starting...

我已经做了几件事:我确保使用 fs.unlink(myFile) 从文件系统中删除,以及在每次成功写入文件后关闭与猫鼬的连接。我正在使用变量 var myFile = file.path (这是来自 ng-file-upload 的文件路径) - 成功写入后,我尝试将 myFile 设置为 null 无济于事。

当我切换视图或刷新页面时它可以工作,但是由于我要使用单页应用程序,所以我想避免这种情况.....

这是我在服务器端的代码:

/**
 * Created by foolishklown on 8/27/2016.
 */
var mongoose = require('mongoose'),
    path = require('path'),
    Grid = require('gridfs-stream'),
    fs = require('fs'),
    User = require('../../models/user');

module.exports = function(file, userId, fileType, res) {
    var fileId;
    //console.log('called the write file for gridfs'.green);
    //console.log('file is: ', file);
    var conn = mongoose.createConnection('mongodb://localhost/media', (error) => {
        if(error) {
            console.error('Error connecting to mongod media instance'.red);
            process.exit(1);
        } else {
            console.info('Connected successfully to mongod media instance in the write file!'.blue);
        }
    });
    // The following line is designating a file to grab/read, and save into mongo
    //  in our case it will be something from ng-file-upload that the user wants to upload
    var myFile = file.path;

    // Connect gridFs and mongo
    Grid.mongo = mongoose.mongo;

    conn.once('open', function () {
        console.log('connection open, ready for I/O!');
        var gfs = Grid(conn.db);

        // This write stream is how well write to mongo
        var writeStream = gfs.createWriteStream({
            // Name the file the way you want it stored in mongo
            filename: file.originalFilename,
            type: fileType
        });

        // Create a read stream, so that we can read its data, and then with that well use the
        //  write stream to write to the DB via piping the writestream
        var readStream = fs.createReadStream(myFile)
            .on('end', () => {
                writeToUserDb(userId, fileType, readStream.id);
                res.status(200).send({id: readStream.id, type: fileType, user: userId});
            })
            .on('error', () => {
                res.status(500).send('error in writing with gridfs');
            })
            .pipe(writeStream);

        //fs.createReadStream(myFile).pipe(writeStream);

        writeStream.on('close', function (file) {
            console.log(file.filename + 'written to DB');
            /**
            setTimeout(1000, () => {
                fs.unlink(myFile);
            });
             */
            fs.unlink(myFile);
            myFile = null;
            conn.close();
        });
    });

    function writeToUserDb(uid, type, fileId) {
        var userConn = mongoose.createConnection('mongodb://localhost/mean-auth', (error) => {
            if(error) {
                console.error('Error connecting to the mean-auth instance'.red);
                process.exit(1);
            } else {
                console.info('Connected to the mean-auth instance!'.blue);
                console.info('Attempting to find user: ' + uid + ', filetype: ' + type + ', streamID: ' + fileId + '!'.green);
                User.findById(uid, (err, doc) => {
                    if(err) {
                        console.error('Error finding user with id: ', uid);
                        process.exit(1);
                    } else {
                        console.log('original doc: ', doc);
                        doc.addMedia(type, fileId);
                        doc.save();
                        console.log('new doc: ', doc);
                    }
                })
            }
        });
        userConn.close();
    }
};
4

1 回答 1

0

唉,这根本不是后端的问题,这是ng文件上传的角度问题......

我的html:

<div class="row">
    <div class="col-lg-10">
        <h1>MyPi Audio</h1>
    </div>
    <div class="col-lg-2">
        <form name="form">
            <input type="file" id="file1" name="file" ng-files="getTheFiles($files)"
                   ng-keep="false"
                   accept="'audio/*'">
            <input type="button" class="btn btn-default" ng-click="uploadFiles('/dashboard/uploadAudio', 'audio', myCont.currentUser)" value="Upload">
        </form>
    </div>
</div>
<div class="row">
  <div ng-repeat="audio in myCont.media.audio" style="width:100%;background-color:#999999;border:1px solid deeppink;">
      <img ng-src="{{audio.url}}" />
      <span>{{audio.name}}</span>
  </div>
</div>

在控制器内部,构建表单数据没有重置......旧代码:

var formdata = new FormData();

    $scope.getTheFiles = function ($files) {        
            angular.forEach($files, function (value, key) {
                //console.log('key: ' + key + ', val: ' + $files[key]);
                formdata.append(key, value);
            });
        }
    };

从服务器发回响应后,我简单地调用了 $scope.getTheFiles(null),并在重置表单数据的函数中添加了对空条件的检查

var formdata = new FormData();

    $scope.getTheFiles = function ($files) {
        if($files == null) {
            formdata = new FormData();
        } else {
            angular.forEach($files, function (value, key) {
                //console.log('key: ' + key + ', val: ' + $files[key]);
                formdata.append(key, value);
            });
        }
    };

我回答了我的问题,以防其他人将来有同样的问题

于 2016-10-06T18:17:55.460 回答