2016-05-13 8 views
2

私は平均値に基づいてthis tutorialを使用しています。 ユーザーがMongoDBを使ってサーバーにアップロードできる写真を保存したい。MEAN.jsを使用して写真をアップロード

が含まれる:Angular directive to upload files

作成-spot.client.view.html

<div data-ng-controller="SpotsCreateController"> 
    <form class="form-signin" data-ng-submit="create(picFile)" novalidate> 
     <label>Upload an image</label> 
     <input type="file" id="articleimage" ng-model="picFile" ng-file-select="" ng-file-change="generateThumb(picFile[0], $files)" multiple name="file" accept="image/*"> 
     <img ng-show="picFile[0].dataUrl != null" ng-src="{{picFile[0].dataUrl}}" class="img-thumbnail" height="50" width="100"> 
     <span class="progress" ng-show="picFile[0].progress >= 0">  
      <div style="width:{{picFile[0].progress}}%" ng-bind="picFile[0].progress + '%'" class="ng-binding"></div> 
     </span> 
     <span ng-show="picFile[0].result">Upload Successful</span> 

     <input type="submit" class="btn btn-lg btn-primary btn-block" ng-click="uploadPic(picFile)"> 

     <div data-ng-show="error"> 
      <strong data-ng-bind="error"></strong> 
     </div> 
    </form> 
</div> 

ビューspot.client.view.html

<div data-ng-controller="SpotsViewController"> 
    <section data-ng-init="findOne()"> 
     <img ng-src="data:image/jpeg;base64,{{spot.image}}" id="image-id" width="200" height="200"/> 
    </section> 
</div> 

application.js

var app = angular.module('newApp', ['ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.bootstrap', 'users', 'spots']); 

spots.create.client.controller.js

angular.module('spots').controller('SpotsCreateController', ['$scope', '$timeout', 'Authentication', 'Spots', '$location' 
function($scope, $timeout, Authentication, Spots, $location) { 
    $scope.authentication = Authentication; 
    $scope.fileReaderSupported = window.FileReader !== null; 

    $scope.create = function(picFile) { 
     var spot = new Spots({ 
      title: this.title, 
      description: this.description, 
      image: null 
     }); 
     spot.$save(function(response) { 
      $location.path('spots/' + response._id); 
     }, function(errorResponse) { 
      $scope.error = errorResponse.data.message; 
     }); 
    }; 

    $scope.doTimeout = function(file) { 
     $timeout(function() { 
      var fileReader = new FileReader(); 
      fileReader.readAsDataURL(file); 
      fileReader.onload = function(e) { 
       $timeout(function() { 
        file.dataUrl = e.target.result; 
       }); 
      }; 
     }); 
    }; 
    $scope.generateThumb = function(file) { 
     if (file) { 
      if ($scope.fileReaderSupported && file.type.indexOf('image') > -1) { 
       $scope.doTimeout(file); 
      } 
     } 
    }; 

spot.server.model.js

var mongoose = require('mongoose'), 
    Schema = mongoose.Schema; 

var SpotSchema = new Schema({ 
    ... 
    image: { 
     type: String, 
     default: '', 
     required: false 
    } 
}); 

mongoose.model('Spot', SpotSchema); 

spots.server.routes.js

var multiparty = require('connect-multiparty'), 
    multipartyMiddleware = multiparty(); 

module.exports = function(app) { 
    app.route('/api/spots') 
     .get(spots.list) 
     .post(users.requiresLogin, multipartyMiddleware, spots.create); 

    app.route('/api/spots/:spotId') 
     .get(spots.read) 
     .put(users.requiresLogin, spots.hasAuthorization, spots.update) 
     .delete(users.requiresLogin, spots.hasAuthorization, spots.delete); 

    app.param('spotId', spots.spotByID); 
}; 

spots.server.controller.js

var mongoose = require('mongoose'), 
    fs = require('fs'), 
    Spot = mongoose.model('Spot'); 

exports.create = function(req, res) { 
    if (req.files.file) { 
     var file = req.files.file; 
    } 

    var spot = new Spot(req.body); 
    spot.creator = req.user; 

    fs.readFile(file.path, function (err,original_data) { 
     if (err) { 
      return res.status(400).send({ 
       message: getErrorMessage(err) 
      }); 
     } 
     var base64Image = original_data.toString('base64'); 
     fs.unlink(file.path, function (err) { 
      if (err) { 
       console.log('failed to delete ' + file.path); 
      } else { 
       console.log('successfully deleted ' + file.path); 
      } 
     }); 
     spot.image = base64Image; 
     spot.save(function(err) { 
      if (err) { 
       return res.status(400).send({ 
        message: getErrorMessage(err) 
       }); 
      } else { 
       res.json(spot); 
      } 
     }); 
    }); 
}; 

私が間違って何をしたのですか?私はファイルサイズを制限したいと考えてください、と私はbase64を使用して良いスタートだと思った。問題は、写真がデータベースに保存されていないということです。なぜなら、コントローラは残りの部分では動作しないからです。

+0

問題は何ですか? – danial

答えて

2

を使用することができますか?

私は通常、ファイルのアップロードを処理するためのmulterミドルウェアを使用しています。また、私は親オブジェクトを保存しているときにそれらを処理しようとするのではなく、ファイルを扱うために別々のルート/コントローラを作成します。これにより、論理をうまく分離でき、ファイルアップロードが失敗したときに親オブジェクトが保存されないことを心配する必要がなくなります。 JS APIをng-file-uploadに使用してAngularで処理できます。 Expressの

例ルート(ここでは "ロゴ" の画像と "クラブ" を持っている):

router.post(
    '/logo', 
    ensureAuthenticated, ensureAdmin, 
    logoCtrl.upload, 
    logoCtrl.save 
); 
router.get(
    '/:clubId/logo.*', 
    logoCtrl.stream 
); 

例コントローラ方法:

let multer = require('multer'); 
module.exports = { 

    /** 
    * Upload logo 
    */ 
    save(req, res, next) { 

    //Get club and file 
    let club = req.user.club; 
    let file = req.file; 

    //Update 
    club.logo = { 
     data: file.buffer, 
     mimeType: file.mimetype 
    }; 

    //Save 
    club.save() 
     .then(() => { 
     res.end(); 
     }) 
     .catch(next); 
    }, 

    /** 
    * Stream logo 
    */ 
    stream(req, res, next) { 
    let club = req.club; 
    res.contentType(club.logo.mimeType); 
    res.send(club.logo.data); 
    }, 

    /** 
    * Upload middleware 
    */ 
    upload(req, res, next) { 

    //Create upload middleware 
    let upload = multer({ 
     storage: multer.memoryStorage(), 
     limits: { 
     fileSize: 50000000 
     } 
    }).single('logo'); 

    //Use middleware 
    upload(req, res, next); 
    } 
}; 

あなたが見ることができるように、それはかなりですMulterミドルウェアを登録してファイルを処理する方法と、MongoDBに保存する方法があります(この場合は、クラブに添付されています)。リクエスト)。

ng-file-uploadが、multerが期待しているファイルをアップロードするために同じフィールド名を使用していることを確認してください。上の例では "ロゴ"です。あなたが不明な場合は、クライアントアプリケーションがサーバーに送信しているものを確認し、サーバーアプリケーションが同じフィールド名を要求していることを確認してください。

さらに問題がある場合はお知らせください。

1

あなたが問題を経験されており、どのようなステップでそれが間違って起こっている正確にどのようなformidablegridfs-stream

//controller 
var mongoose = require('mongoose'), 
    fs = require('fs'), 
    Spot = mongoose.model('Spot'); 

exports.create = function(req, res) { 
    handleRequest(req, function(err, spot) { 
    if(err) { 
     return res.status(400).send({ 
     message: getErrorMessage(err) 
     }); 
    } 

    res.json(spot); 

    }); 
}; 

function handleRequest(req) { 

    var spot = new Spot(req.body); 
    spot.creator = req.user; 

    var formidable = require('formidable'); 

    var form = new formidable.IncomingForm(); 

    form.parse(req, function(err, fields, files) { 
    if (err) { 
     return done(err); 
    } 
    var file = files.qqfile; 
    if (file && file.name && file.name.trim !== '') { 
     if (file.size > 5000000) { 
     message = 'file is too large'; 
     } 
     if (!file.type) { 
     message = 'file is not an image'; 
     } 
     if (file.type.indexOf('image/') !== 0) { 
     message = 'file is not an image type'; 
     } 
    } 
    if (message) { 
     logger.info('Uploading failed', file, message); 
     return done(message); 
    } 

    uploadFile(mongoose.connection, 'Pictures', files.qqfile, require('uuid').v1(), function(err) { 
     if (err) { 
     return done(err); 
     } 
     if (!data) return done(false, null); 

     if (typeof data === 'string') { 
     data = JSON.parse(data); 
     } 
     logger.info('[PHOTOS]', 'Uploaded', data.filename); 
     photo = { 
     unique_id: token, 
     name: file.name, 
     contentType: file.type 
     }; 

     spot.photos = spot.photos || []; 
     spot.photos.push(photo); 
     spot.markModified('photos'); 
     spot.save(done); 

    }); 
    }); 
} 

function uploadFile(DB, className, data, token, callback) { 
    var grid = require('gridfs-stream'); 
    var gfs = grid(DB.db, mongoose.mongo); 

    var writestream = gfs.createWriteStream({ 
    filename: token, 
    root: className 
    }); 
    writestream.on('close', function (file) { 
    return callback(null, file); 
    }); 

    if (data.path) { 
    var fs = require('fs'); 
    if (!fs.existsSync(data.path)) { 
     return callback(false); 
    } 
    var pipe = false; 
    if (data.pipe) { 
     pipe = data.pipe; 
    } else { 
     var fs = require('fs'); 
     if (!fs.existsSync(data.path)) { 
     return callback(false); 
     } 
     var rs = fs.createReadStream(data.path); 
     pipe = rs.pipe.bind(rs); 
    } 
    return pipe(writestream); 
    } else { 
    logger.error('[PHOTO] no path', data); 
    } 
    callback(false); 
} 
+0

あなたの答えに感謝します。あなたのソリューションは全く異なるものです(異なるモジュール、...) –

+0

[更新されました]あなたが好きならば投票し、同意しますか? :) – malix

+0

私は5Mbに制限を設定し、それを少し減らすためにわずかなJPEG圧縮を使用しています... – malix

関連する問題