2014-11-06 79 views
0

我正在使用expressjs并尝试将图像发布到AWS S3,以便在我的应用程序中使用。我一直在关注这个tutorial,虽然我能够成功上传图片,但每次发送的文件名为default_name,我不相信文件格式正在附加到字符串上以便为文件提供正确的图像格式。当我查看教程中提供的s3upload.js脚本时,我注意到default_name是它们为文件提供的标准名称,但我不确定为什么它不接受我的文件而不使用其标题。未被用作AWS S3名称的文件名

事件-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="/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> 
        <input type="submit" value="Submit"><br> 
       </form> 
      </div> 
     </div> 
    </div> 

    <script type="text/javascript" src="/js/s3upload.js" async></script> 

    <script> 
     console.log("S3 Function Launched"); 

     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; 
        console.log(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> 

routes.js:

var express = require('express'); 
var router = express.Router(); 
var Event = require('./models/eventsModel'); 
var http = require('http'); 
var path = require('path'); 
var aws = require('aws-sdk'); 

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; 


    router.get('/sign_s3', function(req, res){ 
     aws.config.update({accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY }); 
     var s3 = new aws.S3(); 
     var s3_params = { 
      Bucket: S3_BUCKET, 
      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://'+S3_BUCKET+'.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.url; 

      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'); 
      }); 
     }); 

s3upload.js:

(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

我遇到了同样的问题来了,这是我我的节点控制器内解决它:

aws.config.update({accessKeyId: AWS_ACCESS_KEY, secretAccessKey: AWS_SECRET_KEY}); 
    var s3 = new aws.S3(); 

    // Set Extension 
    switch(req.query.s3_object_type) { 
     case 'image/png': 
      var ext = '.png'; 
     break; 
     case 'image/gif': 
      var ext = '.gif'; 
     break; 
     case 'image/jpg': 
     case 'image/jpeg': 
      var ext = '.jpg'; 
     break; 
    } 

    // Rename File 
    var name = Math.floor(new Date()/1000); 

    // Set S3 
    var s3_params = { 
     Bucket: S3_BUCKET, 
     Key: 'blog/'+name+ext, 
     Expires: 60, 
     ContentType: req.query.s3_object_type, 
     ACL: 'public-read' 
    }; 

    // Send S3 
    s3.getSignedUrl('putObject', s3_params, function(err, data){ 
     if(err){ 
      console.log(err); 
     } 
     else{ 
      var return_data = { 
       signed_request: data, 
       url: 'https://'+S3_BUCKET+'.s3.amazonaws.com/'+name+ext 
      }; 
      res.write(JSON.stringify(return_data)); 
      res.end(); 
     } 
    }); 

因此,大家可以看到一个非常简单的解决问题的办法,只是检查的延伸和重命名文件。希望这可以帮助。

1

您既可以设置在客户端或服务器端的文件名。

客户端:在事件 - create.ejs,该参数传递给S3Upload:

s3_object_name: $('input[type=file]').val().match(/[^\/\\]+$/)[0] 

服务器端(优选的方法):在routes.js,具有独特取代的req.query.s3_object_name所有实例文件名。您可以使用req.query.s3_object_type来确定您应该放在文件名末尾的扩展名。您希望在此使用唯一的文件名,因为所有内容都存储在同一个存储区中,并且AWS会自动覆盖具有相同文件名的文件。