2013年10月24日 星期四

Read a BIG file in Node.js

寫程式的人常有需要處理到大型的檔案讀取,在Node.js中如果直接使用原生的fs.readFile()來讀檔,則會發生"RangeError: length > kMaxLength"之類的Exception,範例程式如下:

//test-fs.js
var fs = require('fs');
fs.readFile('../1G-File.txt', function(e,d){
  if(e) console.log(e);
  console.log(d);
});

執行的結果如下:

$ node test-fs.js
buffer.js:194
      this.parent = new SlowBuffer(this.length);
                    ^
RangeError: length > kMaxLength
    at new Buffer (buffer.js:194:21)
    at fs.js:220:16
    at Object.oncomplete (fs.js:107:15)


這時候借用第三方套件"lazy"+"fs.createReadStream()"的話,將可以很順利的解決讀取大檔案的問題喔∼

var lazy = require("lazy")
  , fs  = require("fs");
new lazy(fs.createReadStream('../1G-File.txt'))
   .lines
   .forEach(function(line){
       console.log(line.toString());
   }
);

執行上將會很順利...這邊不秀了∼給大家參考






2013年10月22日 星期二

Node.js銜接Google的第一步....

gapitoken

gapitoken是使用Node.js實作Oauth2認證的一個模組,透過API console中申請一個service account,並使用api console產生的p12 key所轉換的pem key,就可以快速的與API進行認證。此種(service account)與API認證的方式適用於提供查詢服務的應用程式,不需要與user的Auth做互動,與API的互動完全是透過應用程式owner所申請的service account之全縣。

套件資訊

Installation

npm install gapitoken

使用說明

準備連線需要的資訊,其中iss為當初申請service account時候的所給的Email address,如下圖:
而Scope是Google控制存取API的呼叫權限,不同的API或不同的request有不同的scope要給予,才可以做呼叫動作,最後,key.pem是創立service account時候所給予的p12檔案,透過ssl轉換後的檔案...
var opts = {
      iss: '860835...6s1@developer.gserviceaccount.com',
      scope: 'https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/cloud-platform',
      keyFile: __dirname + '/key.pem'  
};
準備API pem key
從API console下載的key為副檔名p12的key,需要透過openssl轉換為pem key
$ openssl pkcs12 -in privatekey.p12 -out privatekey.pem -nocerts  
$ openssl rsa -in privatekey.pem -out key.pem

透過GAPI物件,進行Auth連線動作,實際token可以gapi.getToken()的callback中取得...
var gapi = new GAPI(opts, function(err) {
    if (err) return console.log(err);
    gapi.getToken(function(err, token) {
      if (err)  return console.log(err);
      //這邊已經取到token了
      console.log(token);
    });
  });
呼叫API,這邊透過request模組做API的呼叫,其中auth token需要放在header的Authorization中...
var bqurl = 'https://www.googleapis.com/bigquery/v2/projects/%s/queries';  
request({
    url: util.format(bqurl,'your-project-name'),
    method: 'POST',
    headers: {
      "Authorization": "Bearer " + token
    }, 
   json: {
      query: 'select * from cp300.GetAnimals'
    }
  }, function(e,r,d){
    if(e) console.log(e);    //Print the query result
    console.log(JSON.stringify(d));
  });

使用範例 - 連線BigQuery

See:/examples/gapitoken/bq-sample.js

var GAPI = require('gapitoken')
    , request = require('request')
    , fs = require('fs')
    , util = require('util')

    //From admin console, create a service account, save the client_secrets.json and it's key
  var client_secrets = JSON.parse(fs.readFileSync(__dirname + '/client_secrets.json','utf8'))

    //Project setting
  var iss = client_secrets.web.client_email;
  var bq_scope = 'https://www.googleapis.com/auth/bigquery https://www.googleapis.com/auth/cloud-platform';
  var project = 'your-project-name';
  var opts = {
      iss: iss,
      scope: bq_scope,
       keyFile: __dirname + '/key.pem'  };    
  var _token = '';
  var gapi = new GAPI(opts, function(err) {
    if (err) return console.log(err);
     gapi.getToken(function(err, token) {
      if (err)  return console.log(err);
      _token = token;
      var bqurl = 'https://www.googleapis.com/bigquery/v2/projects/%s/queries';      request({
        url: util.format(bqurl,project),
        method: 'POST',
        headers: {
          "Authorization": "Bearer " + _token
        },
        json: {
          query: 'select * from cp300.GetAnimals'
        }
      }, function(e,r,d){
        if(e) console.log(e);        //Print the query result
        console.log(JSON.stringify(d));
      });
    });
  });