2012-12-20 16 views
8

Resimleri s3 üzerinde saklamak için node.js kullanan bir görüntü sunucusu yazmaya çalışıyorum. Görüntüyü yüklemek iyi çalışıyor ve ben bir s3 tarayıcı istemcisi kullanarak düzgün bir şekilde indirip görüntüleyebiliyorum (özellikle de dragondisk kullanıyorum, fakat diğerleriyle de çok yükledim), ancak bunu düğüm ile indirip denediğimde diske yazmak için dosyayı açamıyorum (bozuk ya da Önizleme tanımayan bir dosya formatı kullandığını söylüyor). Dosya yazmak için node ve fs için amazon sdk kullanıyorum. İsteğe bağlı bir kodlamayı fs.writeFile'a aktarabileceğinizi biliyorum, ancak hepsini denedim ve işe yaramıyor. Ayrıca ContentType'ı getObject üzerinde putObject ve ResponseContentType öğelerinin yanı sıra ContentEncoding ve ResponseContentEncoding (ve bunların tümünü çeşitli kombinasyonlarda) üzerinde ayarlamayı denedim. Aynı sonuç. İşte bazı kod: Bu aradanode.js kullanılarak s3 üzerinde saklanan bir görüntü kaydediliyor mu?

var AWS = require('aws-sdk') 
    , gm = require('../lib/gm') 
    , uuid = require('node-uui') 
    , fs = require('fs'); 

AWS.config.loadFromPath('./amazonConfig.json'); 
var s3 = new AWS.S3(); 

var bucket = 'myBucketName'; // There's other logic here to set the bucket name. 

exports.upload = function(req, res) { 
    var id = uuid.v4(); 
    gm.format("/path/to/some/image.jpg", function(format){ 
     var key = req.params.dir + "/" + id + "/default." + format; 
     fs.readFile('/path/to/some/image.jpg', function(err, data){ 
      if (err) { console.warn(err); } 
      else { 
       s3.client.putObject({ 
        Bucket: bucket, 
        Key: key, 
        Body: data, 
        ContentType: 'image/jpeg' 
        // I've also tried adding ContentEncoding (in various formats) here. 
       }).done(function(response){ 
        res.status(200).end(JSON.stringify({ok:1, id: id})); 
       }).fail(function(response){ 
        res.status(response.httpResponse.statusCode).end(JSON.stringify(({err: response}))); 
       }); 
      } 
     }); 
    }); 
}; 

exports.get = function(req, res) { 
    var key = req.params.dir + "/" + req.params.id + "/default.JPEG"; 
    s3.client.getObject({ 
     Bucket: bucket, 
     Key: key, 
     ResponseContentType: 'image/jpeg' 
     // Tried ResponseContentEncoding here in base64, binary, and utf8 
    }).done(function(response){ 
     res.status(200).end(JSON.stringify({ok:1, response: response})); 
     var filename = '/path/to/new/image/default.JPEG'; 
     fs.writeFile(filename, response.data.Body, function(err){ 
      if (err) console.warn(err); 
      // This DOES write the file, just not as an image that can be opened. 
      // I've tried pretty much every encoding as the optional third parameter 
      // and I've matched the encodings to the ResponseContentEncoding and 
      // ContentEncoding above (in case it needs to be the same) 
     }); 
    }).fail(function(response){ 
     res.status(response.httpResponse.statusCode).end(JSON.stringify({err: response})); 
    }); 
}; 

, ben yönlendirme için ekspres kullanıyorum geliyor req.params orası böylece.

+0

Sadece keşfetti 'base64' öğesini kodlama olarak fs.readFile() ve fs.writeFile() yöntemine iletirsem, bunun tersi doğrudur. Hizmetimi kullanarak görüntüyü indirebilir ve görüntüleyebilirim, ancak bir s3 tarayıcı istemcisi kullanarak indirdiğimde bunu görüntüleyemiyorum. İkisini de yapmanın bir yolu var mı? – tandrewnichols

cevap

5

Önemli bir deneme ve hatadan sonra, bunu nasıl yapacağınızı anladım. Knox'e geçtim, ama muhtemelen, aws-sdk ile benzer bir strateji kullanabilirsiniz. Bu, "Bundan daha iyi bir yolu olmalı" dememi sağlayan bir çözümdür, ancak bu noktada işe yarayan hiçbir şeyden memnunum.

var imgData = ""; 
client.getFile(key, function(err, fileRes){ 
    fileRes.on('data', function(chunk){ 
     imgData += chunk.toString('binary'); 
    }).on('end', function(){ 
     res.set('Content-Type', pic.mime); 
     res.set('Content-Length', fileRes.headers['content-length']); 
     res.send(new Buffer(imgData, 'binary')); 
    }); 
}); 

getFile() döner tamponlar gibi veri parçalar. Biri sadece sonuçları doğrudan ön tarafa aktaracağınızı düşünürdü, ama her ne sebeple olursa olsun, bu bir görüntüyü doğru bir şekilde döndürmek için bir servis alabiliyordu. İkili bir dizgeye arabellek yazmak için gereksizdir, sadece bir arabelleğe yazmak için yazıyor, ama eğer işe yararsa, işe yaramaz. Eğer daha verimli bir çözüm bulursa, bunu duymak isterim.

+0

S3, akışın uzunluğunu bekler. Bu, bir kesmek bir şey olduğunu söyledi, ama sen.Oyuna özelliği ayarladıysanız, akışa koyduysanız S3 Gövdesine putObject çağrısı, bu hile yapmış olurdu. –

10

Bu sorunla hala mücadele eden kişiler için. İşte nativ aws-sdk ile kullandığım yaklaşım. yönlendirici yöntemi içinde

var AWS = require('aws-sdk'); 
AWS.config.loadFromPath('./s3_config.json'); 
var s3Bucket = new AWS.S3({ params: {Bucket: 'myBucket'} }); 

: - ContentType görüntü dosyası

buf = new Buffer(req.body.imageBinary.replace(/^data:image\/\w+;base64,/, ""),'base64') 
    var data = { 
    Key: req.body.userId, 
    Body: buf, 
    ContentEncoding: 'base64', 
    ContentType: 'image/jpeg' 
    }; 
    s3Bucket.putObject(data, function(err, data){ 
     if (err) { 
     console.log(err); 
     console.log('Error uploading data: ', data); 
     } else { 
     console.log('succesfully uploaded the image!'); 
     } 
    }); 

s3_config.json dosya içeriği türüne ayarlanmış olmalıdır geçerli: -

{ 
    "accessKeyId":"xxxxxxxxxxxxxxxx", 
    "secretAccessKey":"xxxxxxxxxxxxxx", 
    "region":"us-east-1" 
} 
İlgili konular