it-swarm.com.de

MEAN Stack-Datei-Uploads

Ich habe vor kurzem mit dem Programmieren mit dem MEAN-Stack begonnen und implementiere derzeit eine Art soziales Netzwerk. Ich habe das MEAN.io-Framework verwendet, um dies zu tun . Mein Hauptproblem im Moment ist es, den Datei-Upload zum Laufen zu bringen, denn ich möchte die Datei aus dem Formular in den AngularJS-Controller aufnehmen und mit weitergeben Info zu ExpressJS, damit ich endlich alles an MongoDB schicken kann. (Ich baue ein neues Benutzerformular auf).

Ich möchte nicht die Datei selbst in der Datenbank speichern, aber ich möchte einen Link darauf speichern.

Ich habe Dutzende von Seiten mit verschiedenen Suchanfragen bei Google durchsucht, aber ich konnte nichts finden, was ich verstehen oder arbeiten konnte. Seit Stunden stundenlang nach keinem Ergebnis gesucht. Deshalb bin ich hierher gekommen.

Kann mir jemand dabei helfen?

Vielen Dank :)

BEARBEITEN: Vielleicht hilft ein bisschen Code etwas zu verstehen.

Der standardmäßige MEAN.io-Benutzercontroller Angular, den ich als Grundlage verwende, hat folgende Eigenschaften:

$scope.register = function(){
        $scope.usernameError = null;
        $scope.registerError = null;
        $http.post('/register', {
            email: $scope.user.email,
            password: $scope.user.password,
            confirmPassword: $scope.user.confirmPassword,
            username: $scope.user.username,
            name: $scope.user.fullname
        })//... has a bit more code but I cut it because the post is the main thing here.
    };

Was ich tun möchte, ist: Empfange eine Datei von einem Formular auf diesen Controller und gib sie zusammen mit E-Mail, Passwort, Namen usw. weiter und kann den Json on expressjs verwenden, der auf der Serverseite sitzt ..__ Das '/ register' ist eine Node-Route, also ein Server-Controller, der den Benutzer (mit dem Benutzerschema) erstellt und an die MongoDB sendet.

19
Cacos

Ich habe kürzlich so etwas gemacht. Ich habe angle-file-upload verwendet. Sie möchten auch node-multiparty für Ihren Endpunkt, um die Formulardaten zu parsen. Dann können Sie s3 verwenden, um die Datei nach S3 zu laden.

Hier ist ein Teil meines [bearbeiteten] Codes.

Angular Vorlage

<button>
  Upload <input type="file" ng-file-select="onFileSelect($files)">
</button>

Angular Controller

$scope.onFileSelect = function(image) {
  $scope.uploadInProgress = true;
  $scope.uploadProgress = 0;

  if (angular.isArray(image)) {
    image = image[0];
  }

  $scope.upload = $upload.upload({
    url: '/api/v1/upload/image',
    method: 'POST',
    data: {
      type: 'profile'
    },
    file: image
  }).progress(function(event) {
    $scope.uploadProgress = Math.floor(event.loaded / event.total);
    $scope.$apply();
  }).success(function(data, status, headers, config) {
    AlertService.success('Photo uploaded!');
  }).error(function(err) {
    $scope.uploadInProgress = false;
    AlertService.error('Error uploading file: ' + err.message || err);
  });
};

Route

var uuid = require('uuid'); // https://github.com/defunctzombie/node-uuid
var multiparty = require('multiparty'); // https://github.com/andrewrk/node-multiparty
var s3 = require('s3'); // https://github.com/andrewrk/node-s3-client

var s3Client = s3.createClient({
  key: '<your_key>',
  secret: '<your_secret>',
  bucket: '<your_bucket>'
});

module.exports = function(app) {
  app.post('/api/v1/upload/image', function(req, res) {
    var form = new multiparty.Form();
    form.parse(req, function(err, fields, files) {
      var file = files.file[0];
      var contentType = file.headers['content-type'];
      var extension = file.path.substring(file.path.lastIndexOf('.'));
      var destPath = '/' + user.id + '/profile' + '/' + uuid.v4() + extension;

      var headers = {
        'x-amz-acl': 'public-read',
        'Content-Length': file.size,
        'Content-Type': contentType
      };
      var uploader = s3Client.upload(file.path, destPath, headers);

      uploader.on('error', function(err) {
        //TODO handle this
      });

      uploader.on('end', function(url) {
        //TODO do something with the url
        console.log('file opened:', url);
      });
    });
  });
}

Ich habe dies von meinem Code aus geändert, daher funktioniert es möglicherweise nicht sofort, aber hoffentlich ist es hilfreich!

25
kentcdodds

Kürzlich wurde der Liste der Pakete auf mean.io ein neues Paket hinzugefügt. Es ist eine Schönheit!

Einfach ausführen: 

$ mean install mean-upload

Dadurch wird das Paket im Knotenordner installiert, Sie haben jedoch Zugriff auf die Anweisungen in Ihren Paketen.

http://mean.io/#!/packages/53ccd40e56eac633a3eee335

Fügen Sie in Ihrer Formularansicht Folgendes hinzu:

    <div class="form-group">
        <label class="control-label">Images</label>
        <mean-upload file-dest="'/packages/photos/'" upload-file-callback="uploadFileArticleCallback(file)"></mean-upload>
        <br>
        <ul class="list-group">
            <li ng-repeat="image in article.images" class="list-group-item">
                {{image.name}}
                <span class="glyphicon glyphicon-remove-circle pull-right" ng-click="deletePhoto(image)"></span>
            </li>
        </ul>
    </div>

Und in deinem Controller:

    $scope.uploadFileArticleCallback = function(file) {
      if (file.type.indexOf('image') !== -1){
          $scope.article.images.Push({
            'size': file.size,
            'type': file.type,
            'name': file.name,
            'src': file.src
          });
      }
      else{
          $scope.article.files.Push({
            'size': file.size,
            'type': file.type,
            'name': file.name,
            'src': file.src
          });
      }
    };

    $scope.deletePhoto = function(photo) {
        var index = $scope.article.images.indexOf(photo);
        $scope.article.images.splice(index, 1);
    }

Genießen!

3
jmckenney

Mean-Upload wurde veraltet und heißt jetzt "Upload". Es wird verwaltet in - https://git.mean.io/orit/upload

0
gurpreet-SD

Ich weiß, dass dieser Beitrag alt ist. Ich bin darauf gestoßen und @kentcdodds hatte eine Antwort, die mir sehr gut gefallen hat, aber die von ihm verwendeten Bibliotheken sind veraltet und ich konnte sie nicht zum Laufen bringen. Nach einigen Recherchen habe ich eine neuere ähnliche Lösung, die ich teilen möchte.

HTML mit ng-upload

<form >
    <div style="margin-bottom: 15px;">
        <button type="file" name="file" id="file" ngf-select="uploadFiles($file, $invalidFiles)" accept="image/*" ngf-max-height="1000" ngf-max-size="1MB">Select File</button>
    </div>
</form>

INCLUDE ng-upload module

laden Sie es herunter, referenzieren Sie die Dateien und fügen Sie das Modul hinzu

var app = angular.module('app', ['ngFileUpload']);

dadurch erhalten Sie Zugriff auf den Dienst Upload.

Controller-Code

$scope.uploadFiles = function(file, errFiles) {
    $scope.f = file;
    $scope.errFile = errFiles && errFiles[0];
    if (file) {
        file.upload = Upload.upload({
            url: 'you-api-endpoint',
            data: {file: file}
        });

        //put promise and event watchers here if wanted
    }   
};

NODE-API-Code

Der gesamte unten stehende Code befindet sich in einer separaten route Datei, die required in meiner Hauptdatei server.js ist.

require('./app/app-routes.js')(app, _);

var fs = require('fs');
var uuid = require('uuid');
var s3 = require('s3fs'); // https://github.com/RiptideElements/s3fs
var s3Impl = new s3('bucketname', {
    accessKeyId: '<your access key id>',
    secretAccessKey: '< your secret access key >'
});

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

module.exports = function(app, _) {
    app.use(multipartyMiddleware);


    app.post('/your-api-endpoint',function(req, res){

    var file = req.files.file; // multiparty is what allows the file to to be accessed in the req
    var stream = fs.createReadStream(file.path);
    var extension = file.path.substring(file.path.lastIndexOf('.'));
    var destPath = '/' + req.user._id + '/avatar/' +  uuid.v4() + extension;
    var base = 'https://you-bucket-url';
    return s3Impl.writeFile(destPath, stream, {ContentType: file.type}).then(function(one){
        fs.unlink(file.path);
        res.send(base + destPath); 
    });
});

Ich habe nur versucht, einen einzigartigen Avatar für einen Benutzer hochzuladen. Hoffe das hilft!!

0
TravRob