Reputation: 2428
I have created a Node.js Webservice which takes Json object in the post body and in the same object I need to pass the image/video (not sure whether its possible) media files and the same media file needs to up uploaded to Azure Blob Storage.
Azure storage gives library where we upload the stream. But how do I upload the files to node.js server from Apps before uploading to Azure blob storage.
The concept has to work on Windows, Android and IOS platform.
Upvotes: 1
Views: 3182
Reputation: 13918
If your server is hosted on Web apps and assuming it’s built by expressjs, @Alex Lau provided a good point.
Also, here are another 2 libs for express handling upload files. I’d like to give you some code snippets to handle upload files and put to blob storage in expressjs with these libs:
var busboy = require('connect-busboy');
var azure = require('azure-storage');
var fs = require('fs');
var path = require('path');
var blobsrv = azure.createBlobService(
accountname,
accountkey
)
router.post('/file', function (req, res, next) {
var fstream;
var uploadfolder = path.join(__dirname, '../files/');
if (mkdirsSync(uploadfolder)) {
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
console.log("Uploading: " + filename);
fstream = fs.createWriteStream(uploadfolder + filename);
file.pipe(fstream);
fstream.on('close', function () {
//res.redirect('back');
blobsrv.createBlockBlobFromLocalFile('mycontainer',filename,uploadfolder + filename, function (error, result, response) {
if (!error) {
res.send(200, 'upload succeeded');
} else {
res.send(500, 'error');
}
})
});
});
}
})
function mkdirsSync(dirpath, mode) {
if (!fs.existsSync(dirpath)) {
var pathtmp;
dirpath.split("\\").forEach(function (dirname) {
console.log(dirname);
if (pathtmp) {
pathtmp = path.join(pathtmp, dirname);
}
else {
pathtmp = dirname;
}
if (!fs.existsSync(pathtmp)) {
if (!fs.mkdirSync(pathtmp, mode)) {
return false;
}
}
});
}
return true;
}
var formidable = require('formidable')
router.post('/fileform', function (req, res, next) {
var form = new formidable.IncomingForm();
form.onPart = function (part){
part.on('data', function (data){
console.log(data);
var bufferStream = new stream.PassThrough();
bufferStream.end(data);
blobsrv.createBlockBlobFromStream('mycontainer', part.filename, bufferStream, data.length, function (error, result, response){
if (!error) {
res.send(200,'upload succeeded')
} else {
res.send(500,JSON.stringify(error))
}
})
})
}
form.parse(req);
//res.send('OK');
})
If you are using a Mobile Apps with Node.js as a backend to handle these workflows, we can create a custom API, and transfer media content in base64 code.
In mobile app:
var azure = require('azure');
var fs = require('fs');
var path = require('path');
exports.register = function (api) {
api.post('upload',upload);
}
function upload(req,res){
var blobSvc = azure.createBlobService(
req.service.config.appSettings.STORAGE_ACCOUNTNAME,
req.service.config.appSettings.STORAGE_ACCOUNTKEY
);
var decodedImage = new Buffer(req.body.imgdata, 'base64');
var tmpfilename = (new Date()).getTime()+'.jpg';
var tmpupload = 'upload/';
mkdirsSync(tmpupload);
var filePath = tmpupload+tmpfilename;
fs.writeFileSync(filePath,decodedImage); blobSvc.createBlockBlobFromFile(req.body.container,tmpfilename,filePath,req.body.option,function(error,result,response){
if(!error){
res.send(200,{result:true});
}else{
res.send(500,{result:error});
}
})
}
In mobile application, I used iconic framework integrated ng-cordova plugin to handle camera events. Here are controller and server script snippet. For your information:
Controller js:
$scope.getpic = function(){
var options = {
quality: 10,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: false,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function(imageData) {
console.log(imageData);
return blobService.uploadBlob(objectId,imageData);
}, function(err) {
// error
}).then(function(res){
console.log(JSON.stringify(res));
});
};
Server js(blobService):
factory('blobService',function($q){
return{
uploadBlob:function(container,imgdata,option){
var q = $q.defer();
mobileServiceClient.invokeApi('blobstorage/upload',{
method:"post",
body:{
container:container,
imgdata:imgdata,
option:{contentType:'image/jpeg'}
}
}).done(function(res){
console.log(JSON.stringify(res.result));
if(res.result.blob !== undefined){
q.resolve(res.result.blob);
}
if(res.result.url !== undefined){
q.resolve(res.result.url);
}
});
return q.promise;
}
}
})
Upvotes: 2
Reputation: 1697
Perhaps you may consider using multipart/form-data
instead of JSON as there is a good library (expressjs/multer, assuming you are using express
) to handle file uploading in node.js.
As long as you get the file from multer, the rest can be very simple as below:
app.post('/profile', upload.single('avatar'), function (req, res, next) {
blobService.createBlockBlobFromLocalFile('avatars', req.file.originalname, req.file.path, function(error, result, response) {
});
});
For iOS and Android, there are also plenty of libraries that allow multipart/form-data
request like AFNetworking in iOS and OkHttp in Android.
Upvotes: 0