『葉狂人』的怕失憶筆記 Back-End

用 node.js 來搞定 AutoPatch 軟體的自動更新

用 node.js 來搞定 AutoPatch 軟體的自動更新

node.js 真的是方便好用的程式語言,效率也很不錯,可以輕易的與 Win32 Application 結合

Client 端我是使用 C++ Builder 來實作,主要用於更新客戶的執行檔,DLL 等等的函式庫

記得以前還沒有 node.js 的時候,Server 端也是用 C++ Builder 來開發,但是缺點是必須 Run 於 Windows 平台上

這對目前 VPS 盛行,大部分都是 Linux 主機無疑是一大阻礙,如今有了 node.js

很多 Socket 或是 HTTP 通訊的工作都轉而使用 node.js 來開發

var http  = require("http"),
    url   = require('url'),
    path  = require('path'),
    fs    = require('fs'),
    async = require('async');

var ReadFileObject = function (item, callback) {
  var ReadFileObject = this;
  this.resultFiles = [];
  this.readSizeRecursive = function (item, cb) {
    fs.lstat(item, function (err, stats) {
      if (!err && stats.isDirectory()) {
        fs.readdir(item, function (err, list) {
          if (err) return cb(err);
          async.each(
            list,
            function (diritem, callback) {
              ReadFileObject.readSizeRecursive(path.join(item, diritem), function (err, size) {
                if (typeof size !== 'undefined' && diritem[0] != '.') {
                  ReadFileObject.resultFiles.push({
                    name : diritem,
                    size : size.size,
                    crc32 : 0
                  });
                }
                callback(err);
              });
            },
            function (err) {
              cb(err);
            }
          );
        });
      }
      else {
        cb(err, stats);
      }
    });
  };
  this.readSizeRecursive(item, function () {
    callback(ReadFileObject.resultFiles);
  });
};

var server = http.createServer(function (req, res) {
  var url_parts = url.parse(decodeURI(req.url), true);
  switch (url_parts.pathname) {
    case '/' :
      if (typeof url_parts.query.package != 'undefined' && url_parts.query.package != '') {
        url_parts.query.package = path.normalize(url_parts.query.package.toLowerCase());
        var _file = path.join(__dirname, url_parts.query.package);
        if (_file.match(__dirname + '/') && _file != __dirname + '/' && fs.existsSync(_file)) {
          var autoPatch = new ReadFileObject(_file, function (resultFiles) {
            console.log(url_parts.query.package, resultFiles, resultFiles.length);
            if (typeof url_parts.query.json === 'undefined') {
              res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
              async.each(
                resultFiles,
                function (currentValue, callback) {
                  res.write(currentValue.name.toString() + '\n');
                  res.write(currentValue.size.toString() + '\n');
                  res.write(currentValue.crc32.toString() + '\n');
                  callback();
                },
                function (err) {
                  res.end();
                }
              );
            }
            else {
              res.writeHead(200, {'Content-Type': 'application/json; charset=utf-8'});
              res.end(JSON.stringify(resultFiles));
            }
            autoPatch = null;
          });
        }
        else {
          if (typeof url_parts.query.json === 'undefined') {
            res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
            res.end();
          }
          else {
            res.writeHead(200, {'Content-Type': 'application/json; charset=utf-8'});
            res.end(JSON.stringify([]));
          }
        }
      }
      else {
        res.writeHead(500);
        res.end('HTTP 500');
      }
    break;
    default :
      var _file = path.join(__dirname, url_parts.pathname);
      if (_file.match(__dirname + '/') && fs.existsSync(_file)) {
        fs.lstat(_file, function (err, stats) {
          if (!err && stats.isFile()) {
            console.log(_file, 'Starting patch.');
            res.writeHead(200, {
              "Content-Type" : 'application/x-msdownload',
              "Content-Disposition" : "attachment",
              "Content-Transfer-Encoding" : "binary",
              "Content-Length" : stats.size
            });
            fs.createReadStream(_file).pipe(res);
          }
          else {
            res.writeHead(500);
            res.end('HTTP 500');
          }
        });
      }
      else {
        res.writeHead(404);
        res.end('HTTP 404');
      }
    break;
  }
});

server.listen(3002, function () {
  console.log('server is listening');
});
『葉狂人』的怕失憶筆記, author
「想像力就是貨真價實的魔毯。」
《積極思考的力量》作者、美國作家 諾曼文生皮爾