问题
I am trying to use the azure-sdk-for-node to save a streamed image to Windows Azure blob storage but without success. Below is the function that I call and pass the video object with the thumbnail property. Initially I fetch the image using the request object which fetches the image from another website and turn that into a base64 object which in turn gets converted into a stream object because Azure blob service uses createBlockBlobFromStream method as I couldn't use createBlockBlobFromFile or createBlockBlobFromText to upload the image to blob storage.
var azure = require('azure')
, uuid = require('node-uuid')
, http = require('http')
, url = require('url')
, mmm = require('mmmagic')
, Magic = mmm.Magic
, stream = require('stream');
function createVideoThumbnail(video, callback){
var bs = azure.createBlobService(config.storageAccount, config.storageAccessKey, config.blobHost);
var sURL = video.Thumbnail;
var oURL = url.parse(sURL);
var client = http.createClient(80, oURL.hostname);
var request = client.request('GET', oURL.pathname, {'host': oURL.hostname});
request.end();
request.on('response', function (response) {
var type = response.headers["content-type"];
var prefix = "data:" + type + ";base64,";
var body = "";
response.setEncoding('binary');
response.on('end', function () {
var base64 = new Buffer(body, 'binary').toString('base64');
var data = prefix + base64;
console.log('base64 image data ' + video.Thumbnail + ': ' + data + '\n');
var decodedImage = new Buffer(data, 'base64');
var magic = new Magic(mmm.MAGIC_MIME_TYPE);
magic.detect(decodedImage, function(err, result) {
if(err) {
throw err;
}
var bytes = 0;
var imageStream = new stream.Stream();
imageStream.writable = true;
imageStream.write = function(buf) {
bytes += buf.length;
imageStream.emit('data', buf);
};
imageStream.end = function(buf) {
//if(arguments.length) {
imageStream.write(buf);
//}
imageStream.writable = false;
imageStream.emit('end');
console.log(bytes + ' bytes written');
};
var options = {}
console.log('mmm = ' + result + '\n');
options.contentType = result;
options.contentTypeHeader = result;
console.log('\n');
bs.createBlockBlobFromStream(config.imageContainer, uuid().replace(/-/gi, "").toLowerCase() + '.jpg', imageStream, decodedImage.length, options, function(error, blobResult, response) {
if (error)
console.log('got error = ' + JSON.stringify(error) + '\n');
if (blobResult)
console.log('blobResult = ' + JSON.stringify(blobResult) + '\n');
if (response)
console.log('response = ' + JSON.stringify(response) + '\n');
// now store in Azure blob storage
callback();
});
imageStream.end(decodedImage);
});
});
response.on('data', function (chunk) {
if (response.statusCode == 200) body += chunk;
});
});
}
and this is how I call it:
createVideoThumbnail(video, function(){
console.log("returning from create thumbnails\n\n");
});
The function is not working it hangs and won't print out the the final log statement:
console.log("returning from create thumbnails\n\n");
However the base64 does seem to work as I am getting this for the encoding:
data:image/jpeg;base64,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
mmm = application/octet-stream 5283 bytes written
But I am not getting any of these log statements being printed:
if (error)
console.log('got error = ' + JSON.stringify(error) + '\n');
if (blobResult)
console.log('blobResult = ' + JSON.stringify(blobResult) + '\n');
if (response)
console.log('response = ' + JSON.stringify(response) + '\n');
So I am presuming it is hanging somewhere or I have not structured my code properly. Can anybody see what I am doing wrong ?
Cheers Rob
My sources:
http://social.msdn.microsoft.com/Forums/en-US/wavirtualmachinesforlinux/thread/47bfe142-c459-4815-b09e-bd0a07ca18d5
Node.js base64 encode a downloaded image for use in data URI
回答1:
Here's my simplified version. Since magic needs to operate on the whole file, there's no point in using the streaming blog API, instead this is written for the text api. body
will be a buffer of the image, I suspect azure will be happy with it sans encoding, call toString('encoding') if it does need it.
var azure = require('azure')
, uuid = require('node-uuid')
, request = require('request')
, mmm = require('mmmagic')
, Magic = mmm.Magic
, stream = require('stream')
, bs = azure.createBlobService(config.storageAccount, config.storageAccessKey, config.blobHost);
function createVideoThumbnail(video, callback){
var sURL = video.Thumbnail;
request(sURL, {encoding:null}, function (err, res, body) {
// encoding:null makes request return a buffer, which is ideal to run magic.detect on
magic.detect(body, function (err, res) {
console.log(res);
var container = config.imageContainer;
var blob = uuid().replace(/-/gi, "").toLowerCase() + '.jpg';
var text = body; //might need to be converted into a string, I don't have azure setup to test
var options = {
contentType: res,
contentTypeHeader: res
};
bs.createBlockBlobFromText(container, blob, text, options, function(error, blobResult, response) {
if (error)
console.log('got error =', error);
// if you give console.log multiple arguments, it will format each of them,
// no need to manipulate objects into strings manually
if (blobResult)
console.log('blobResult =', blobResult);
if (response)
console.log('response =', response);
// now store in Azure blob storage
callback();
});
});
});
}
edit: temp file version
var azure = require('azure')
, uuid = require('node-uuid')
, request = require('request')
, mmm = require('mmmagic')
, Magic = mmm.Magic
, fs = require('fs')
, bs = azure.createBlobService(config.storageAccount, config.storageAccessKey, config.blobHost);
function createVideoThumbnail(video, callback){
var sURL = video.Thumbnail;
var name = uuid().replace(/-/gi, "").toLowerCase() + '.jpg';
var ws = fs.createWriteStream('./tmp/' + name);
request(sURL, {encoding:null})
.pipe(ws).on('close', function () {
console.log('downloaded');
magic.detectFile('./tmp/' + name, function (err, res) {
var container = config.imageContainer;
var blob = uuid().replace(/-/gi, "").toLowerCase() + '.jpg';
var options = {
contentType: res,
contentTypeHeader: res
};
bs.createBlockBlobFromFile(container, name, './tmp/' + name, function (err) {
callback();
});
});
});
}
回答2:
Thanks to Valery Jacobs on msdn forums was able to come up with the answer. It's a nice clean solid solution using the stream, request and util object.
:)
http://social.msdn.microsoft.com/Forums/en-US/windowsazurepurchasing/thread/25c7705a-4ea0-4d9c-af09-cb48a031d06c
来源:https://stackoverflow.com/questions/15450102/create-thumbnail-image-using-windows-azure-blob-storage