I am trying to improve our existing file upload API (using sinatra) and see 
if Node can be a better alternative.
i am using formidable to upload the file, than I stream(read) the file from 
disk into put request that saves it on our cloud servers, and finally, I 
save some meta data into a mysql. 
I make sure nothing is blocking and never load the file into memory, by 
using streaming.

please review my code and let me know what can I improve.
also, i tested it with jmeter and here are the results: 
http://i.imgur.com/PSWjH.png?1http://i.imgur.com/PSWjH.png?1
I set it up with 20 concurrent connections for 1 minute.

the problem with my test is it relies on the network connection and i don't 
really know how much time was spent on the server itself, 
how much memory, cpu and bandwidth was used? what is the speed of disk 
writes my server can handle?

one idea i can think of is taking samples from top command on the server to 
figure out the memory and cpu.
any tips/tools ideas or other things i should do?

here <http://pastebin.com/xmh281hq> is most of the code (with syntax 
highlight) and I also pasted it here: 

// server.js

process.env.TMP = '/tmp/upload';

// core modules
var http = require('http');
var util = require('util');

// non-core packages
var formidable = require('formidable'); // easy handling of file uploads
var mysql = require('mysql');

// my modules
var saveMeta = require('./saveMeta.js'); // save name in mysql
var saveFile = require('./saveFile.js'); // save file on my private cloud

var connection = mysql.createConnection({
  host     : 'localhost',
  database : 'test',
  user     : '',
  password : '',
});

connection.connect();

http.createServer(function(req, res) {
  // curl -F "myupload=@/pic.JPG" 0.0.0.0:3001/api -v
  if (req.url == '/api' && req.method.toLowerCase() == 'post') {
    // parse a file upload
    var form = new formidable.IncomingForm();
    
    form.parse(req, function(err, fields, files) {
      res.writeHead(200);
      res.end();
    });
    
    form.on('file', function(name, file) {
      //save file in private cloud and save meta info in mysql
      saveFile(connection, file.name, file.path, saveMeta);
    });
    
    return;
  }

}).listen(3001);


// ---------------------------------
// saveFile.js

module.exports = saveFile;

var fs = require('fs');
var request = require('request');


// get file size and send to my cloud
//
// arguments:
// connection - mysql connection
// name - original file name
// path - path on temp directory
// saveMeta -  callback for saving into mysql
function saveFile(connection, name, path, saveMeta) {
  //adding a random number to file name. my cloud require unique names
  var rand = Math.floor(Math.random()*100000000).toString(); 
  var url = 'http://my-private-cloud.com:5000/test-' + rand;

  function getFileSize(cb) {
    fs.stat(path, function(err, stats) {
      if(err) {
        console.log('error while reading the file:' + path, err);
      } else {
        if(cb) {
          cb(stats.size);
        }
      }
    });
  };

  // stream(read) the file from hardrive into put request that saves it on 
our cloud
  //
  // curl -sSf -T file1 http://my-private-cloud.com:5000/test
  // 200 - file was saved
  // anything else - file was not saved
  function sendFileToCloud(fileSize) {
    var file = fs.createReadStream(path)
      .pipe(request.put({url: url, headers:{'Content-Length': fileSize}}, 
function(err, res, body){
        if(err) {
          console.log('error in PUT request to my cloud:', err);
        } else {
          // console.log('status from cloud:', res.statusCode);
          // console.log('file url:', url);
          if(res.statusCode === 200) {
            saveMeta(connection, name, path, url) 
          }
        }
      }));
    
    file.on('data', function(chunk) {
    })

    file.on('end', function() {
    });

    file.on('error', function(e) {
      console.log('error:', e);
    });
  };

  getFileSize(sendFileToCloud);
};

-- 
Job Board: http://jobs.nodejs.org/
Posting guidelines: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nodejs@googlegroups.com
To unsubscribe from this group, send email to
nodejs+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Reply via email to