我一直关注Heroku" Direct to S3 File Uploads in Node.js"能够从我的AWS S3存储桶上传和显示图像。我为这个项目中使用的存储桶做了CORS配置,但我没有看到任何图像上传到我的存储桶而且无法显示任何图像。当我尝试使用console.log我的onError方法进行文件上传时,我得到undefined
。我POST
时没有遇到任何错误。以下是我的代码:
eventsModel.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var EventSchema = new Schema({
name: String,
title: String,
company: String,
url: String,
date: { type: Date, default: Date.now },
speakerImage: String
});
module.exports = mongoose.model('Event', EventSchema);
routes.js:
var express = require('express');
var router = express.Router();
var Event = require('./models/eventsModel');
router.get('/sign_s3', function(req, res){
aws.config.update({accessKeyId: "My Access Key", secretAccessKey: "My Secret Key"});
var s3 = new aws.S3();
var s3_params = {
Bucket: "My Bucket Name",
Key: req.query.s3_object_name,
Expires: 60,
ContentType: req.query.s3_object_type,
ACL: 'public-read'
};
s3.getSignedUrl('putObject', s3_params, function(err, data){
if(err){
console.log(err);
}
else{
var return_data = {
signed_request: data,
url: 'https://'+"My Bucket Name"+'.s3.amazonaws.com/'+req.query.s3_object_name
};
res.write(JSON.stringify(return_data));
res.end();
}
});
});
router.route('/admin/events/create')
.post(function(req, res){
var events = new Event();
events.name = req.body.name;
events.title = req.body.title;
events.company = req.body.company;
events.url = req.body.url;
events.speakerImage = req.body.speakerImage;
events.save(function(err){
if (err)
res.send(err);
res.redirect(303, '/events');
});
})
.get(function(req, res){
Event.find(function(err, events){
if (err)
res.send(err);
res.render('pages/events-create.ejs');
});
});
router.route('/admin/events/:events_id')
.get(function(req, res){
Event.findById(req.params.events_id, function(err, events){
if (err)
res.send(err);
res.json(events);
});
})
.put(function(req, res){
Event.findById(req.params.events_id, function(err, events){
if (err)
res.send(err);
res.json({ message: 'Event Updated'});
});
});
//GET '/events'
router.get('/events', function(req, res) {
Event.find({})
.sort({'date': -1})
.exec(function(err, events) {
if (err)
res.send(err);
console.log(events.speakerImage);
console.log(events.name);
res.render('pages/events.ejs', {
events : events
});
});
});
事件-create.ejs:
<!DOCTYPE HTML>
<html>
<head>
<% include ../partials/head %>
</head>
<body>
<% include ../partials/navigation %>
<div class="grid" id="create-event-container">
<div class="col-1-1">
<div id="create-event">
<h1><i>Create Event</i></h1>
<input type="file" id="files"/>
<p id="status">Please select a file</p>
<div id="preview"><img src="/images/event-placeholder.png"></div>
<form action="/admin/events/create" method="POST">
<input type="hidden" id="speaker-image" name="speakerImage" value="public/images/event-placeholder.png" />
Name: <input type="text" name="name"><br>
Title: <input type="text" name="title"><br>
Company: <input type="text" name="company"><br>
Website: <input type="text" name="url"><br>
Upcoming Event?: <input type="checkbox" name="upcomingEvent"><br>
<input type="submit" value="Submit"><br>
</form>
</div>
</div>
</div>
<script type="text/javascript" src="/js/s3upload.js">
<script>
function s3_upload(){
var status_elem = document.getElementById("status");
var url_elem = document.getElementById("speaker-image");
var preview_elem = document.getElementById("preview");
var s3upload = new S3Upload({
file_dom_selector: 'files',
s3_sign_put_url: '/sign_s3',
onProgress: function(percent, message) {
status_elem.innerHTML = 'Upload progress: ' + percent + '% ' + message;
},
onFinishS3Put: function(public_url) {
status_elem.innerHTML = 'Upload completed. Uploaded to: '+ public_url;
url_elem.value = public_url;
preview_elem.innerHTML = '<img src="'+public_url+'" style="width:300px;" />';
},
onError: function(status) {
status_elem.innerHTML = 'Upload error: ' + status;
console.log(status_elem.innerHTML);
}
});
}
/*
* Listen for file selection:
*/
(function() {
var input_element = document.getElementById("files");
input_element.onchange = s3_upload;
})();
</script>
</body>
</html>
server.js:
//Load Express
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var eventsDb = require('./config/eventsDb');
var http = require('http');
var path = require('path');
var aws = require('aws-sdk');
app.use(bodyParser.urlencoded({ extended: true})); //get data from a POST method
app.use(bodyParser.json());
mongoose.connect(eventsDb.url);
var port = process.env.PORT || 8080; //set port
app.set('view engine', 'ejs'); //set EJS template engine
app.use(express.static(__dirname + '/public')); // set the public directory
var AWS_ACCESS_KEY = process.env.AWS_ACCESS_KEY;
var AWS_SECRET_KEY = process.env.AWS_SECRET_KEY;
var S3_BUCKET = process.env.S3_BUCKET
var Event = require('./app/models/eventsModel');
var routes = require('./app/routes');
app.use(routes);
app.listen(port);
console.log('access at port:' + port);
s3upload.js(也可以在博客文章的repo中访问):
(function() {
window.S3Upload = (function() {
S3Upload.prototype.s3_object_name = 'default_name';
S3Upload.prototype.s3_sign_put_url = '/signS3put';
S3Upload.prototype.file_dom_selector = 'file_upload';
S3Upload.prototype.onFinishS3Put = function(public_url) {
return console.log('base.onFinishS3Put()', public_url);
};
S3Upload.prototype.onProgress = function(percent, status) {
return console.log('base.onProgress()', percent, status);
};
S3Upload.prototype.onError = function(status) {
return console.log('base.onError()', status);
};
function S3Upload(options) {
if (options == null) options = {};
for (option in options) {
this[option] = options[option];
}
this.handleFileSelect(document.getElementById(this.file_dom_selector));
}
S3Upload.prototype.handleFileSelect = function(file_element) {
var f, files, output, _i, _len, _results;
this.onProgress(0, 'Upload started.');
files = file_element.files;
output = [];
_results = [];
for (_i = 0, _len = files.length; _i < _len; _i++) {
f = files[_i];
_results.push(this.uploadFile(f));
}
return _results;
};
S3Upload.prototype.createCORSRequest = function(method, url) {
var xhr;
xhr = new XMLHttpRequest();
if (xhr.withCredentials != null) {
xhr.open(method, url, true);
} else if (typeof XDomainRequest !== "undefined") {
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
xhr = null;
}
return xhr;
};
S3Upload.prototype.executeOnSignedUrl = function(file, callback) {
var this_s3upload, xhr;
this_s3upload = this;
xhr = new XMLHttpRequest();
xhr.open('GET', this.s3_sign_put_url + '?s3_object_type=' + file.type + '&s3_object_name=' + this.s3_object_name, true);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.onreadystatechange = function(e) {
var result;
if (this.readyState === 4 && this.status === 200) {
try {
result = JSON.parse(this.responseText);
} catch (error) {
this_s3upload.onError('Signing server returned some ugly/empty JSON: "' + this.responseText + '"');
return false;
}
return callback(result.signed_request, result.url);
} else if (this.readyState === 4 && this.status !== 200) {
return this_s3upload.onError('Could not contact request signing server. Status = ' + this.status);
}
};
return xhr.send();
};
S3Upload.prototype.uploadToS3 = function(file, url, public_url) {
var this_s3upload, xhr;
this_s3upload = this;
xhr = this.createCORSRequest('PUT', url);
if (!xhr) {
this.onError('CORS not supported');
} else {
xhr.onload = function() {
if (xhr.status === 200) {
this_s3upload.onProgress(100, 'Upload completed.');
return this_s3upload.onFinishS3Put(public_url);
} else {
return this_s3upload.onError('Upload error: ' + xhr.status);
}
};
xhr.onerror = function() {
return this_s3upload.onError('XHR error.');
};
xhr.upload.onprogress = function(e) {
var percentLoaded;
if (e.lengthComputable) {
percentLoaded = Math.round((e.loaded / e.total) * 100);
return this_s3upload.onProgress(percentLoaded, percentLoaded === 100 ? 'Finalizing.' : 'Uploading.');
}
};
}
xhr.setRequestHeader('Content-Type', file.type);
xhr.setRequestHeader('x-amz-acl', 'public-read');
return xhr.send(file);
};
S3Upload.prototype.uploadFile = function(file) {
var this_s3upload;
this_s3upload = this;
return this.executeOnSignedUrl(file, function(signedURL, publicURL) {
return this_s3upload.uploadToS3(file, signedURL, publicURL);
});
};
return S3Upload;
})();
}).call(this);
答案 0 :(得分:0)
旧问题,但我想我会很快发现其他人的错误(不确定是否还有其他错误)。
在router.js文件中,您需要:
var aws = require('aws-sdk');
另请确保在您的用户(“权限” - >“托管策略”)下将AmazonS3FullAccess附加到您的帐户。