2013-07-29 10 views
22

Ich bin ratlos, was ich tue, falsch, hier ist mit, was ich habe:Einfache Datei-Upload bis S3 aws-sdk und Node/Express

HTML

<html> 
<body> 
    <form method="POST" action="/upload" enctype="multipart/form-data"> 
     <div class="field"> 
      <label for="image">Image Upload</label> 
      <input type="file" name="image" id="image"> 
     </div> 
     <input type="submit" class="btn" value="Save"> 
    </form> 
</body> 
</html> 

Port 5000 ist mein Node.js Server-Port. In diesem Beispiel verwende ich POST zu /upload, und es funktioniert gut.

module.exports = function(app, models) { 

    var fs = require('fs'); 
    var AWS = require('aws-sdk'); 
    var accessKeyId = process.env.AWS_ACCESS_KEY || "xxxxxx"; 
    var secretAccessKey = process.env.AWS_SECRET_KEY || "+xxxxxx+B+xxxxxxx"; 

    AWS.config.update({ 
     accessKeyId: accessKeyId, 
     secretAccessKey: secretAccessKey 
    }); 

    var s3 = new AWS.S3(); 

    app.post('/upload', function(req, res){ 

     var params = { 
      Bucket: 'makersquest', 
      Key: 'myKey1234.png', 
      Body: "Hello" 
     }; 

     s3.putObject(params, function (perr, pres) { 
      if (perr) { 
       console.log("Error uploading data: ", perr); 
      } else { 
       console.log("Successfully uploaded data to myBucket/myKey"); 
      } 
     }); 
    }); 

} 

Jetzt möchte ich die Datei schreiben, die ich POST ing bin, das ist, wo das Problem auftritt.

module.exports = function(app, models) { 

    var fs = require('fs'); 
    var AWS = require('aws-sdk'); 
    var accessKeyId = process.env.AWS_ACCESS_KEY || "xxxxxx"; 
    var secretAccessKey = process.env.AWS_SECRET_KEY || "+xxxxxx+B+xxxxxxx"; 

    AWS.config.update({ 
     accessKeyId: accessKeyId, 
     secretAccessKey: secretAccessKey 
    }); 

    var s3 = new AWS.S3(); 

    app.post('/upload', function(req, res){ 
     var path = req.files.image.path; 
     fs.readFile(path, function(err, file_buffer){ 
      var params = { 
       Bucket: 'makersquest', 
       Key: 'myKey1234.png', 
       Body: file_buffer 
      }; 

      s3.putObject(params, function (perr, pres) { 
       if (perr) { 
        console.log("Error uploading data: ", perr); 
       } else { 
        console.log("Successfully uploaded data to myBucket/myKey"); 
       } 
      }); 
     }); 
    }); 
} 

Der Fehler, den ich bekommen ist:

TypeError: Cannot read property 'path' of undefined

als eine Angelegenheit der Tatsache files völlig leer ist.

Ich nehme ich etwas ziemlich offensichtlich fehle aber ich kann es nicht zu finden scheinen.

+0

Welche Version von Knoten verwenden Sie? Sie können überprüfen mit "node -v" –

Antwort

0

Es sieht aus wie Ihre req.files.image nicht definiert ist. console.log aus, was req.files.image zurückgibt und ob Sie von dort aus weitermachen können.

+0

Dateien Objekt scheint aus irgendeinem Grund vollständig leer sein. Was muss ich in der Knotenkonfiguration tun? Ich habe meine HTML-Namen überprüft und überprüft und sie scheinen korrekt zu sein. – abritez

2

Klingt wie Sie nicht die ausdrückliche bodyParser Middleware-Setup haben könnten. Können Sie Ihre gesamte Server-Datei schreiben (app.js, server.js, was Sie haben)

+0

das ist der Grund – atom2ueki

1

Statt multipart/form-data, können Sie image/png oder was auch immer die richtige MIME-Typ ist versuchen, verwenden.

1

Sie brauchen so etwas wie multer in Ihrer Reihe von Middleware multipart/form-data für Sie zu behandeln und req.files zu füllen. Vom doco:

var express = require('express') 
var multer = require('multer') 

var app = express() 
app.use(multer({ dest: './uploads/'})) 

Jetzt req.files.image.path sollte in Ihrer app.post Funktion bestückt werden.

22

Sie werden so etwas wie multer benötigen mehrteiliger Hochladen zu handhaben. Hier ist ein Beispiel, wie Sie Ihren Datei-Upload mit aws-sdk auf s3 streamen.

var multer = require('multer'); 
var AWS = require('aws-sdk'); 

var accessKeyId = process.env.AWS_ACCESS_KEY || "xxxxxx"; 
var secretAccessKey = process.env.AWS_SECRET_KEY || "+xxxxxx+B+xxxxxxx"; 

AWS.config.update({ 
    accessKeyId: accessKeyId, 
    secretAccessKey: secretAccessKey 
}); 

var s3 = new AWS.S3(); 

app.use(multer({ // https://github.com/expressjs/multer 
    dest: './public/uploads/', 
    limits : { fileSize:100000 }, 
    rename: function (fieldname, filename) { 
    return filename.replace(/\W+/g, '-').toLowerCase(); 
    }, 
    onFileUploadData: function (file, data, req, res) { 
    // file : { fieldname, originalname, name, encoding, mimetype, path, extension, size, truncated, buffer } 
    var params = { 
     Bucket: 'makersquest', 
     Key: file.name, 
     Body: data 
    }; 

    s3.putObject(params, function (perr, pres) { 
     if (perr) { 
     console.log("Error uploading data: ", perr); 
     } else { 
     console.log("Successfully uploaded data to myBucket/myKey"); 
     } 
    }); 
    } 
})); 

app.post('/upload', function(req, res){ 
    if(req.files.image !== undefined){ // `image` is the field name from your form 
     res.redirect("/uploads"); // success 
    }else{ 
     res.send("error, no file chosen"); 
    } 
}); 
+1

In diesem Beispiel, sollte ich lokale Datei entfernen? wie zB ', onFileUploadComplete: function (file, req, res) { fs.unlink (datei.pfad) }' –

16

Neueste Antwort @ Dec-2016 [Neu]

Verwenden multer-s3 für mehrt Upload ohne wie auf der lokalen Festplatte zu speichern S3:

var express = require('express'), 
    aws = require('aws-sdk'), 
    bodyParser = require('body-parser'), 
    multer = require('multer'), 
    multerS3 = require('multer-s3'); 

aws.config.update({ 
    secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 
    accessKeyId: 'XXXXXXXXXXXXXXX', 
    region: 'us-east-1' 
}); 

var app = express(), 
    s3 = new aws.S3(); 

app.use(bodyParser.json()); 

var upload = multer({ 
    storage: multerS3({ 
     s3: s3, 
     bucket: 'bucket-name', 
     key: function (req, file, cb) { 
      console.log(file); 
      cb(null, file.originalname); //use Date.now() for unique file keys 
     } 
    }) 
}); 

//open in browser to see upload form 
app.get('/', function (req, res) { 
    res.sendFile(__dirname + '/index.html'); 
}); 

//use by upload form 
app.post('/upload', upload.array('upl',1), function (req, res, next) { 
    res.send("Uploaded!"); 
}); 

app.listen(3000, function() { 
    console.log('Example app listening on port 3000!'); 
}); 

Neueste Antwort @ Mar-2016 [Old-One]

Bearbeitet 1Verwendung[email protected]und[email protected]für Snippet folgende:

var express = require('express'), 
    bodyParser = require('body-parser'), 
    multer = require('multer'), 
    s3 = require('multer-s3'); 

var app = express(); 

app.use(bodyParser.json()); 

var upload = multer({ 
    storage: s3({ 
     dirname: '/', 
     bucket: 'bucket-name', 
     secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 
     accessKeyId: 'XXXXXXXXXXXXXXX', 
     region: 'us-east-1', 
     filename: function (req, file, cb) { 
      cb(null, file.originalname); //use Date.now() for unique file keys 
     } 
    }) 
}); 

//open in browser to see upload form 
app.get('/', function (req, res) { 
    res.sendFile(__dirname + '/index.html'); 
}); 

//use by upload form 
app.post('/upload', upload.array('upl'), function (req, res, next) { 
    res.send("Uploaded!"); 
}); 

app.listen(3000, function() { 
    console.log('Example app listening on port 3000!'); 
}); 

Für komplettes Beispiel Klon express_multer_s3 repo laufen und node app laufen.

+5

Fehler mit diesem Code bekommen 'default: neuen TypeError werfen ('Expected opts.s3 to be object') ^ Typeerror: Erwartete opts.s3 Objekt bei neuen S3Storage (M zu sein: \ Arbeitsplatz \ Angular2StartKit \ node_modules \ multer-s3 \ index.js: 66: 20) bei module.exports (M: \ Arbeitsbereich \ Angular2StartKit \ node_modules \ multer-s3 \ index.js: 150: 10) ' – user2180794

+0

Woher weiß ich, ob der Upload erfolgreich war oder nicht und dann den Bildschirm basierend darauf umleiten. Kannst du mir bitte zeigen, wie das gemacht wird? Ich benutze 'Multer-S3' – Illep

+0

** Antwort wurde aktualisiert ** @ user2180794 hoffe, beide Schnipsel arbeiten für Sie jetzt –

0

Dieser Stapelüberlauf war die beste Antwort, die ich fand, genau erklärend, wie man Knoten zu S3 arbeitet.

AWS Missing credentials when i try send something to my S3 Bucket (Node.js)

Dies zusätzlich zu etwas mehr Sachen, die ich hatte zu hacken auf, um alles zum Laufen zu bringen. In meiner Situation verwendete ich eine MEAN-Stack-Anwendung, so dass meine Knotendatei, mit der ich arbeitete, eine Routendatei war.

meine aconfig.json Datei mit den Amazon-Anmeldeinformationen wie folgt aussieht:

{ "accessKeyId": "*****YourAccessKey****", "secretAccessKey": "***YourSecretKey****" } 

Der endgültige Inhalt der Routendatei aussehen wie die unten stehende Datei eingefügt.

router.post('/sendToS3', function(req, res) { 

var fs = require('fs'); 
var multer = require('multer'); 
var AWS = require('aws-sdk'); 
var path = require('path'); 

var awsCredFile = path.join(__dirname, '.', 'aconfig.json'); 

console.log('awsCredFile is'); 
console.log(awsCredFile); 

AWS.config.loadFromPath(awsCredFile); 

var s3 = new AWS.S3(); 

var photoBucket = new AWS.S3({params: {Bucket: 'myGreatBucketName'}}); 

var sampleFile = { 
    "_id" : 345345, 
    "fieldname" : "uploads[]", 
    "originalname" : "IMG_1030.JPG", 
    "encoding" : "7bit", 
    "mimetype" : "image/jpeg", 
    "destination" : "./public/images/uploads", 
    "filename" : "31a66c51883595e74ab7ae5e66fb2ab8", 
    "path" : "/images/uploads/31a66c51883595e74ab7ae5e66fb2ab8", 
    "size" : 251556, 
    "user" : "579fbe61adac4a8a73b6f508" 
}; 

var filePathToSend = path.join(__dirname, '../public', sampleFile.path); 


function uploadToS3(filepath, destFileName, callback) { 
    photoBucket 
     .upload({ 
      ACL: 'public-read', 
      Body: fs.createReadStream(filepath), 
      Key: destFileName.toString(), 
      ContentType: 'application/octet-stream' // force download if it's accessed as a top location 
     }) 
     // http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3/ManagedUpload.html#httpUploadProgress-event 
     .on('httpUploadProgress', function(evt) { console.log(evt); }) 
     // http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3/ManagedUpload.html#send-property 
     .send(callback); 
} 

multer({limits: {fileSize:10*1024*1024}}); 

console.log('filePathToSend is '); 
console.log(filePathToSend); 

uploadToS3(filePathToSend, sampleFile.filename, function (err, data) { 
    if (err) { 
     console.error(err); 
     return res.status(500).send('failed to upload to s3').end(); 
    } 
    res.status(200) 
     .send('File uploaded to S3: ' 
      + data.Location.replace(/</g, '&lt;') 
      + '<br/><img src="' + data.Location.replace(/"/g, '&quot;') + '"/>') 
     .end(); 
}); 

console.log('uploading now...'); 

}); 

Dies dauerte eine Weile, endlich zum Laufen zu bringen, aber der Weg unten, wenn Sie Setup, aktualisieren Sie die sampleFile JSON zu einer echten Datei auf Ihrem System zu zeigen und schlagen sie mit Postman wird es eine Datei veröffentlichen, um Ihre S3-Konto.

Hoffe das hilft

+0

Bitte zögern Sie nicht, die Antwort zu beschreiben, obwohl der Link zu der detaillierten Ansicht davon führt. – Gar