From d95c744b338deae2fbe0527fca15bdb1f1850e6c Mon Sep 17 00:00:00 2001 From: iwillwen Date: Sat, 17 May 2014 12:09:37 +0800 Subject: [PATCH 01/10] [Update] Put Stream `end` event's bug 1. Update package.json 2. Fixed `end` event has been fired on `bucket.createPutStream` Signed-off-by: iwillwen --- lib/bucket.js | 1 - package.json | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/bucket.js b/lib/bucket.js index 830587d..43962f8 100644 --- a/lib/bucket.js +++ b/lib/bucket.js @@ -138,7 +138,6 @@ Bucket.prototype.createPutStream = function(key, options) { return stream.emit('error', err); } - stream.emit('end', result); stream.emit('complete', result); }); diff --git a/package.json b/package.json index 597ff52..c95e14d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/iwillwen/nodejs-sdk" + "url": "https://www.npmjs.org/package/node-qiniu" }, "keywords": [ "cloud", @@ -33,7 +33,7 @@ "author": "iwillwen", "license": "MIT", "bugs": { - "url": "https://github.com/iwillwen/nodejs-sdk/issues" + "url": "https://www.npmjs.org/package/node-qiniu/issues" }, "dependencies": { "underscore": "~1.5.1", From 77791a4d95ebb2b10f374a93f8ee8db6dd86b66e Mon Sep 17 00:00:00 2001 From: iwillwen Date: Sat, 17 May 2014 12:09:37 +0800 Subject: [PATCH 02/10] Update test case Signed-off-by: iwillwen --- lib/bucket.js | 1 - package.json | 4 ++-- test/qiniu_asset.js | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/bucket.js b/lib/bucket.js index 830587d..43962f8 100644 --- a/lib/bucket.js +++ b/lib/bucket.js @@ -138,7 +138,6 @@ Bucket.prototype.createPutStream = function(key, options) { return stream.emit('error', err); } - stream.emit('end', result); stream.emit('complete', result); }); diff --git a/package.json b/package.json index 597ff52..c95e14d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/iwillwen/nodejs-sdk" + "url": "https://www.npmjs.org/package/node-qiniu" }, "keywords": [ "cloud", @@ -33,7 +33,7 @@ "author": "iwillwen", "license": "MIT", "bugs": { - "url": "https://github.com/iwillwen/nodejs-sdk/issues" + "url": "https://www.npmjs.org/package/node-qiniu/issues" }, "dependencies": { "underscore": "~1.5.1", diff --git a/test/qiniu_asset.js b/test/qiniu_asset.js index 47b929b..e9edb63 100644 --- a/test/qiniu_asset.js +++ b/test/qiniu_asset.js @@ -10,7 +10,7 @@ describe('qiniu.Asset', function() { it('should return the url of the asset', function() { var url = asset.url(); - assert.equal(url, 'http://qiniu-sdk-test.u.qiniudn.com/gogopher.jpg'); + assert.equal(url, 'http://qiniu-sdk-test.qiniudn.com/gogopher.jpg'); }); }); From 1da3a97a85bfc17a1cac5c2741a305a22c1fa85f Mon Sep 17 00:00:00 2001 From: iwillwen Date: Sat, 17 May 2014 12:52:41 +0800 Subject: [PATCH 03/10] Update version --- lib/qiniu.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/qiniu.js b/lib/qiniu.js index ace7e03..86fd0b8 100644 --- a/lib/qiniu.js +++ b/lib/qiniu.js @@ -2,7 +2,7 @@ var _ = require('underscore'); var qiniu = exports; -qiniu.version = '6.1.5'; +qiniu.version = '6.1.6'; var _configData = require('./config'); diff --git a/package.json b/package.json index c95e14d..19a4953 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-qiniu", - "version": "6.1.5", + "version": "6.1.6", "description": "Qiniu Resource Storage SDK for Node.js", "main": "index.js", "directories": { From 7e7e20c58951a25e9af2bcd36518158be046554d Mon Sep 17 00:00:00 2001 From: iwillwen Date: Sun, 18 Jan 2015 22:55:07 +0800 Subject: [PATCH 04/10] Removed dataStream and using strea.Transform modified: .gitignore modified: .npmignore modified: .travis.yml modified: README.md modified: example.js modified: lib/batch.js modified: lib/bucket.js modified: lib/config.js modified: lib/image.js modified: lib/token.js modified: lib/utils.js modified: package.json modified: test/index.js modified: test/qiniu_batch.js modified: test/qiniu_get.js modified: test/qiniu_image.js modified: test/qiniu_put.js --- .gitignore | 3 +- .npmignore | 32 +- .travis.yml | 8 +- README.md | 1036 +++++++++++++++++++++---------------------- example.js | 606 ++++++++++++------------- lib/batch.js | 282 ++++++------ lib/bucket.js | 36 +- lib/config.js | 8 +- lib/image.js | 534 +++++++++++----------- lib/token.js | 228 +++++----- lib/utils.js | 38 +- package.json | 104 ++--- test/index.js | 21 +- test/qiniu_batch.js | 126 +++--- test/qiniu_get.js | 68 +-- test/qiniu_image.js | 432 +++++++++--------- test/qiniu_put.js | 72 +-- 17 files changed, 1820 insertions(+), 1814 deletions(-) diff --git a/.gitignore b/.gitignore index 11110c5..4f8c004 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,5 @@ test/assets/* node_modules coverage.html **.txt -npm_debug.log \ No newline at end of file +npm_debug.log +.npmignore \ No newline at end of file diff --git a/.npmignore b/.npmignore index ae28bac..4b52936 100644 --- a/.npmignore +++ b/.npmignore @@ -1,17 +1,17 @@ -lib-cov -*.seed -*.log -*.csv -*.dat -*.out -*.pid -*.gz - -pids -logs -results - -node_modules -**.txt -npm_debug.log +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +node_modules +**.txt +npm_debug.log .git \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index df63076..a9d69e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -language: node_js -node_js: - - "0.10" - - "0.8" +language: node_js +node_js: + - "0.10" + - "0.8" diff --git a/README.md b/README.md index 5b22bd4..b8d3d7a 100644 --- a/README.md +++ b/README.md @@ -1,518 +1,518 @@ -# 七牛 Node.js SDK - -该 SDK 适用于 Node.js 0.4.7 及其以上版本,基于 七牛云存储官方API 构建。 若您的服务端是一个基于 Node.js 编写的网络程序,使用此 SDK , 能让您以非常便捷地方式将数据安全地存储到七牛云存储上。 以便让您应用的终端用户进行高速上传和下载,同时也使得您的服务端更加轻盈。 - -## 安装 - -你可以从 npm 进行安装 - -```shell -npm install node-qiniu -``` - -也可以从 Github 进行下载安装 - -```shell -$ git clone git://github.com/qiniu/node-qiniu -$ cd node-qiniu -$ npm install . -``` - -## 测试 - -七牛 Node.js SDK 使用 Mocha 进行单元测试。 - -```shell -$ npm install -g mocha -$ make test -``` - -## 使用 - -### 配置 `qiniu.config()` - -设置全局参数,包括必须的 AccessKey 和 SecretKey,还可以设置其他如 CallbackURL 等参数,将会顺延至所有空间。 - -```js -qiniu.config({ - access_key: '------', - secret_key: '------' -}); -``` - -### Bucket - -获得空间对象并进行操作。 - -```js -var imagesBucket = qiniu.bucket('qiniu-sdk-test'); -// 也可以这样操作 -// var imagesBucket = new qiniu.Bucket('qiniu-sdk-test'); -``` - -#### 上传文件 - -**1. `Bucket.putFile()`** - -上传一个文件,参数为将要上传的 Key,文件地址(可以是绝对地址,也可以是相对地址),第三个为可选参数 options,即本次上传中所使用 PutToken 的特殊设置,第四个为可选参数回调(callback),若不传入回调函数,将由 putFile 函数所返回的 Promise 对象进行响应。 - -```js -// 普通上传 -imagesBucket.putFile('exampleKey', __dirname + '/assets/example.jpg', function(err, reply) { - if (err) { - return console.error(err); - } - - console.dir(reply); -}); -// 特殊参数 -imagesBucket.putFile('exampleKey_1', __dirname + '/assets/example.jpg', { - // 为本次上传中所使用的 Token 进行设置,此处为设置上传者标识 - endUser: 'foobar' -}, function(err, reply) { - if (err) { - return console.error(err); - } - - console.dir(reply); -}); -// 七牛 Node.js SDK 所提供的 Promise 对象遵循 Promise/A(+) 标准,使用 .then 方法进行响应 -imagesBucket.putFile('exampleKey_2', __dirname + '/assets/example.jpg') - .then( - function(reply) { - // 上传成功 - console.dir(reply); - }, - function(err) { - // 上传失败 - console.error(err); - } - ); -``` - -**2. `Bucket.createPutStream()`** - -七牛 Node.js SDK 提供基于流(Stream)的操作方式,为熟悉 Node.js 流式操作的开发者提供方便快捷的高性能 API。 - -```js -var puttingStream = imagesBucket.createPutStream('exampleKey_3'); -var readingStream = fs.createReadStream(__dirname + '/assets/example.jpg'); - -readingStream.pipe(puttingStream) - .on('error', function(err) { - console.error(err); - }) - .on('end', function(reply) { - console.dir(reply); - }); -``` - -#### 下载文件 - -`Bucket.getFile()`和`Bucket.createGetStream()` - -获取文件与上传文件同样简单,和 Node.js 中原生的文件系统(File System)的 API 有相似之处。 - -```js -imagesBucket.getFile('exampleKey', function(err, data) { - if (err) { - return console.error(err); - } - - // data 为包含文件数据的 Buffer 对象 -}); -``` - -同样的,获取文件也可以使用流式操作进行 -```js -var gettingStream = imagesBucket.createGetStream('exampleKey'); -var writingStream = fs.createWriteStream(__dirname + '/assets/example_tmp.jpg'); - -gettingStream.pipe(writingStream) - .on('error', function(err) { - console.error(err); - }) - .on('finish', function() { - // 文件数据已写入本地文件系统 - }); -``` - -### `Image` 图片操作 - -七牛 Node.js SDK 提供`Image`类,用于对图片资源进行操作。 - -使用 Bucket.image() 方法获取一个图像对象 - -```js -var image = imagesBucket.image('exampleKey'); -``` - -#### `Image.imageInfo()` - -Image.imageInfo 方法可以用于获取图片资源的图片信息。 -详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageInfo](http://docs.qiniu.com/api/v6/image-process.html#imageInfo) - -```js -image.imageInfo(function(err, info) { - if (err) { - return console.error(err); - } - - console.dir(info); -}); -``` - -#### `Image.exif()` - -Image.imageView 方法用于生成指定规格的缩略图。 -详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageView](http://docs.qiniu.com/api/v6/image-process.html#imageView) - -```js -image.exif(function(err, exif) { - if (err) { - return console.error(err); - } - - console.dir(exif); -}); -``` - -#### `Image.imageView()` - -Image.imageView 方法用于生成指定规格的缩略图。 -详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageView](http://docs.qiniu.com/api/v6/image-process.html#imageView) - -```js -image.imageView({ - mode : 2, - width : 180, - height : 180, - quality : 85, - format : 'jpg' -}, function(err, imageData) { - if (err) { - return console.error(err); - } - - // imageData 为处理过后的图像数据 -}); -``` - -其中,图片对象中的所有含图片数据返回的方法可以使用流式操作。不传入第二个的 callback 参数,而在调用方法的括弧后再调用`.stream()`方法,则会返回一个会不断输出数据的 IO 流。 - -```js -var imageViewStream = image.imageView({ - mode : 2, - width : 180, - height : 180, - quality : 85, - format : 'jpg' -}).stream(); -var writingStream = fs.createWriteStream(__dirname + '/assets/example_thumbnail.jpg'); - -imageViewStream.pipe(writingStream) - .on('error', function(err) { - console.error(err); - }) - .on('finish', function() { - // 缩略图已写入本地文件系统 - }); -``` - -诸如此类: -```js -image.imageMogr(...).stream(); -image.watermark(...).stream(); -image.alias(...).stream(); -``` - -#### `Image.imageMogr()` - -Image.imageMogr 方法用于调用高级图像处理接口,并返回处理后的图片数据。 -详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageMogr](http://docs.qiniu.com/api/v6/image-process.html#imageMogr) - -```js -image.imageMogr({ - thumbnail : '300x500', - gravity : 'NorthWest', - crop : '!300x400a10a10', - quality : 85, - rotate : 90, - format : 'jpg' -}, function(err, imageData) { - if (err) { - return console.error(err); - } - - // 使用 imageData 进行操作 -}); -``` - -#### `Image.watermark()` - -Image.watermark 方法用于生成一个带有水印的图片,图片水印 API 支持图片水印和文字水印两种模式。 -详细请看:http://docs.qiniu.com/api/v6/image-process.html#watermark - -```js -image.watermark({ - mode: 1, - image: 'http://www.b1.qiniudn.com/images/logo-2.png', - dissolve: 70, - gravity: 'SouthEast', - dx: 20, - dy: 20 -}, function(err, imageData) { - if (err) { - return console.error(err); - } - - // 使用 imageData 进行操作 -}); -``` - -#### `Image.alias()` - -Image.alias 方法用于返回既定的数据处理格式的数据,使用此方法需要在[七牛开发者平台](https://portal.qiniu.com)中对设置进行操作。 -其中,`Image.alias()`方法继承于 key 所用的`Asset`类。 - -```js -image.alias('testalias', function(err, imageData) { - if (err) { - return console.error(err); - } - - // 使用 imageData 进行操作 -}); -``` - -### `Asset` 资源操作 - -七牛 Node.js SDK 提供一个`Asset`类,用于对所属资源进行操作。 - -获取 key 所对应资源对象 -```js -var picture = imagesBucket.key('exampleKey'); -``` - -#### `Asset.url()` - -`Asset.url()`方法可以获得该资源的 URL 地址以用于访问 - -```js -var picUrl = picture.url(); -``` - -#### `Asset.entryUrl()` - -`Asset.entryUrl()`方法可以获得该资源用于 API 调用时所需的 EncodedEntryURL。 -但是在 Node.js SDK 中,大部分 API 都不需要开发者自行使用。:) - -```js -var encodedPicUrl = picture.entryUrl(); -``` - -#### `Asset.stat()` - -Asset.stat 方法可以获得该资源的如文件大小、MIME 类型等 stat 数据。 - -```js -picture.stat(function(err, stat) { - if (err) { - return console.error(err); - } - - console.dir(stat); - /** - * { - * hash : , // string 类型,文件的Hash值 - * fsize : , // int 类型,文件的大小(单位: 字节) - * mimeType : , // string 类型,文件的媒体类型,比如"image/gif" - * putTime : // int64 类型,文件上传到七牛云的时间(Unix时间戳) - * } - */ -}); -``` - -#### `Asset.move()` - -`Asset.move()`方法用于移动该资源到指定的位置。 -第一个参数可以是来自其他 Bucket 所属的资源对象。 - -```js -picture.move(imagesBucket.key('exampleKey_4'), function(err) { - if (err) { - return console.error(err); - } - - // 此处没有返回值,如果没有错误,则为操作成功,以下方法相同 -}); -``` - -#### `Asset.copy()` - -`Asset.copy()`方法用于为该资源创建一个拷贝,并保存到指定的资源位置。 - -```js -imagesBucket.key('exampleKey_4').copy(picture, function(err) { - if (err) { - return console.error(err); - } -}); -``` - -#### `Asset.remove()` - -`Asset.remove()`方法用于删除当前资源。 - -```js -imagesBucket.key('exampleKey_4').remove(function(err) { - if (err) { - return console.error(err); - } -}); -``` - -#### `Asset.token()` - -`Asset.token()`方法用于生成当前资源的下载凭证。 - -```js -var getToken = imagesBucket.key('exampleKey').token(); - -console.dir(getToken); -/*=> - { - url: '', - token: '', - requestUrl: 'URL without token' - } - */ - } -``` - -#### `Asset.download()` - -`Asset.download()`方法用于生成当前资源的下载链接。(不包含下载凭证) - -```js -var url = imagesBucket.key('exampleKey').download(); -``` - -### `Batch` 资源批量操作 - -在支持对单个文件资源操作的同时,七牛云存储还支持批量地对多个文件进行查看、删除、复制和移动操作。 -详细请看:http://docs.qiniu.com/api/v6/rs.html#batch - -生成一个批量操作的控制器 -```js -var batch = qiniu.batch(); -``` - -`Batch`中大部分参数与资源对象`Asset`类似,支持查看、移动、复制和删除操作。 - -```js -batch - // 获取文件信息 - .stat(imagesBucket.key('exampleKey')) - // 移动资源 - .move(imagesBucket.key('exampleKey'), imagesBucket.key('exampleKey_5')) - // 复制资源 - .copy(imagesBucket.key('exampleKey_5'), imagesBucket.key('exampleKey')) - // 删除资源 - .remove(imagesBucket.key('exampleKey_5')) - // 执行操作 - // 每一个操作都按照前后顺序进行执行 - .exec(function(err, results) { - if (err) { - return console.error(err); - } - - console.dir(results); - // results 为每一个操作的结果 - }); -``` - -### `Fop` 管道操作 - -七牛云存储提供一个非常实用的资源处理 API,可以用于对资源进行多种处理的操作。 - -例: 将一个原图缩略,然后在缩略图上打上另外一个图片作为水印 - -使用`Asset.fop()`方法创建 Fop 管道操作器,并进行操作。 - -```js -var image = imagesBucket.key('exampleKey'); -// Image.fop 方法继承于 Asset 类 - -image.fop() - // 对图片进行缩略 - .imageView({ - mode : 2, - height : 200 - }) - // 为图片打上水印 - .watermark({ - mode : 1, - image : 'http://www.b1.qiniudn.com/images/logo-2.png' - }) - // 执行操作 - .exec(function(err, imageData) { - if (err) { - return console.error(err); - } - - // imageData 为已打上水印的缩略图数据 - }); -``` - -#### `Fop.token()` - -该方法用于生成当前 Fop 的下载凭证。 - -```js -var image = imagesBucket.key('exampleKey'); -// Image.fop 方法继承于 Asset 类 - -var getToken = image.fop() - // 对图片进行缩略 - .imageView({ - mode : 2, - height : 200 - }) - // 为图片打上水印 - .watermark({ - mode : 1, - image : 'http://www.b1.qiniudn.com/images/logo-2.png' - }) - .token(); - -console.log(getToken.url); -``` - -## 模块结构 -![模块结构](http://ww2.sinaimg.cn/large/7287333fgw1e8263cvxeaj20mr0glgmp.jpg) - -## License - - (The MIT License) - - Copyright (c) 2010-2013 Will Wen Gunn and other contributors - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - 'Software'), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# 七牛 Node.js SDK + +该 SDK 适用于 Node.js 0.4.7 及其以上版本,基于 七牛云存储官方API 构建。 若您的服务端是一个基于 Node.js 编写的网络程序,使用此 SDK , 能让您以非常便捷地方式将数据安全地存储到七牛云存储上。 以便让您应用的终端用户进行高速上传和下载,同时也使得您的服务端更加轻盈。 + +## 安装 + +你可以从 npm 进行安装 + +```shell +npm install node-qiniu +``` + +也可以从 Github 进行下载安装 + +```shell +$ git clone git://github.com/qiniu/node-qiniu +$ cd node-qiniu +$ npm install . +``` + +## 测试 + +七牛 Node.js SDK 使用 Mocha 进行单元测试。 + +```shell +$ npm install -g mocha +$ make test +``` + +## 使用 + +### 配置 `qiniu.config()` + +设置全局参数,包括必须的 AccessKey 和 SecretKey,还可以设置其他如 CallbackURL 等参数,将会顺延至所有空间。 + +```js +qiniu.config({ + access_key: '------', + secret_key: '------' +}); +``` + +### Bucket + +获得空间对象并进行操作。 + +```js +var imagesBucket = qiniu.bucket('qiniu-sdk-test'); +// 也可以这样操作 +// var imagesBucket = new qiniu.Bucket('qiniu-sdk-test'); +``` + +#### 上传文件 + +**1. `Bucket.putFile()`** + +上传一个文件,参数为将要上传的 Key,文件地址(可以是绝对地址,也可以是相对地址),第三个为可选参数 options,即本次上传中所使用 PutToken 的特殊设置,第四个为可选参数回调(callback),若不传入回调函数,将由 putFile 函数所返回的 Promise 对象进行响应。 + +```js +// 普通上传 +imagesBucket.putFile('exampleKey', __dirname + '/assets/example.jpg', function(err, reply) { + if (err) { + return console.error(err); + } + + console.dir(reply); +}); +// 特殊参数 +imagesBucket.putFile('exampleKey_1', __dirname + '/assets/example.jpg', { + // 为本次上传中所使用的 Token 进行设置,此处为设置上传者标识 + endUser: 'foobar' +}, function(err, reply) { + if (err) { + return console.error(err); + } + + console.dir(reply); +}); +// 七牛 Node.js SDK 所提供的 Promise 对象遵循 Promise/A(+) 标准,使用 .then 方法进行响应 +imagesBucket.putFile('exampleKey_2', __dirname + '/assets/example.jpg') + .then( + function(reply) { + // 上传成功 + console.dir(reply); + }, + function(err) { + // 上传失败 + console.error(err); + } + ); +``` + +**2. `Bucket.createPutStream()`** + +七牛 Node.js SDK 提供基于流(Stream)的操作方式,为熟悉 Node.js 流式操作的开发者提供方便快捷的高性能 API。 + +```js +var puttingStream = imagesBucket.createPutStream('exampleKey_3'); +var readingStream = fs.createReadStream(__dirname + '/assets/example.jpg'); + +readingStream.pipe(puttingStream) + .on('error', function(err) { + console.error(err); + }) + .on('end', function(reply) { + console.dir(reply); + }); +``` + +#### 下载文件 + +`Bucket.getFile()`和`Bucket.createGetStream()` + +获取文件与上传文件同样简单,和 Node.js 中原生的文件系统(File System)的 API 有相似之处。 + +```js +imagesBucket.getFile('exampleKey', function(err, data) { + if (err) { + return console.error(err); + } + + // data 为包含文件数据的 Buffer 对象 +}); +``` + +同样的,获取文件也可以使用流式操作进行 +```js +var gettingStream = imagesBucket.createGetStream('exampleKey'); +var writingStream = fs.createWriteStream(__dirname + '/assets/example_tmp.jpg'); + +gettingStream.pipe(writingStream) + .on('error', function(err) { + console.error(err); + }) + .on('finish', function() { + // 文件数据已写入本地文件系统 + }); +``` + +### `Image` 图片操作 + +七牛 Node.js SDK 提供`Image`类,用于对图片资源进行操作。 + +使用 Bucket.image() 方法获取一个图像对象 + +```js +var image = imagesBucket.image('exampleKey'); +``` + +#### `Image.imageInfo()` + +Image.imageInfo 方法可以用于获取图片资源的图片信息。 +详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageInfo](http://docs.qiniu.com/api/v6/image-process.html#imageInfo) + +```js +image.imageInfo(function(err, info) { + if (err) { + return console.error(err); + } + + console.dir(info); +}); +``` + +#### `Image.exif()` + +Image.imageView 方法用于生成指定规格的缩略图。 +详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageView](http://docs.qiniu.com/api/v6/image-process.html#imageView) + +```js +image.exif(function(err, exif) { + if (err) { + return console.error(err); + } + + console.dir(exif); +}); +``` + +#### `Image.imageView()` + +Image.imageView 方法用于生成指定规格的缩略图。 +详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageView](http://docs.qiniu.com/api/v6/image-process.html#imageView) + +```js +image.imageView({ + mode : 2, + width : 180, + height : 180, + quality : 85, + format : 'jpg' +}, function(err, imageData) { + if (err) { + return console.error(err); + } + + // imageData 为处理过后的图像数据 +}); +``` + +其中,图片对象中的所有含图片数据返回的方法可以使用流式操作。不传入第二个的 callback 参数,而在调用方法的括弧后再调用`.stream()`方法,则会返回一个会不断输出数据的 IO 流。 + +```js +var imageViewStream = image.imageView({ + mode : 2, + width : 180, + height : 180, + quality : 85, + format : 'jpg' +}).stream(); +var writingStream = fs.createWriteStream(__dirname + '/assets/example_thumbnail.jpg'); + +imageViewStream.pipe(writingStream) + .on('error', function(err) { + console.error(err); + }) + .on('finish', function() { + // 缩略图已写入本地文件系统 + }); +``` + +诸如此类: +```js +image.imageMogr(...).stream(); +image.watermark(...).stream(); +image.alias(...).stream(); +``` + +#### `Image.imageMogr()` + +Image.imageMogr 方法用于调用高级图像处理接口,并返回处理后的图片数据。 +详细请看:[http://docs.qiniu.com/api/v6/image-process.html#imageMogr](http://docs.qiniu.com/api/v6/image-process.html#imageMogr) + +```js +image.imageMogr({ + thumbnail : '300x500', + gravity : 'NorthWest', + crop : '!300x400a10a10', + quality : 85, + rotate : 90, + format : 'jpg' +}, function(err, imageData) { + if (err) { + return console.error(err); + } + + // 使用 imageData 进行操作 +}); +``` + +#### `Image.watermark()` + +Image.watermark 方法用于生成一个带有水印的图片,图片水印 API 支持图片水印和文字水印两种模式。 +详细请看:http://docs.qiniu.com/api/v6/image-process.html#watermark + +```js +image.watermark({ + mode: 1, + image: 'http://www.b1.qiniudn.com/images/logo-2.png', + dissolve: 70, + gravity: 'SouthEast', + dx: 20, + dy: 20 +}, function(err, imageData) { + if (err) { + return console.error(err); + } + + // 使用 imageData 进行操作 +}); +``` + +#### `Image.alias()` + +Image.alias 方法用于返回既定的数据处理格式的数据,使用此方法需要在[七牛开发者平台](https://portal.qiniu.com)中对设置进行操作。 +其中,`Image.alias()`方法继承于 key 所用的`Asset`类。 + +```js +image.alias('testalias', function(err, imageData) { + if (err) { + return console.error(err); + } + + // 使用 imageData 进行操作 +}); +``` + +### `Asset` 资源操作 + +七牛 Node.js SDK 提供一个`Asset`类,用于对所属资源进行操作。 + +获取 key 所对应资源对象 +```js +var picture = imagesBucket.key('exampleKey'); +``` + +#### `Asset.url()` + +`Asset.url()`方法可以获得该资源的 URL 地址以用于访问 + +```js +var picUrl = picture.url(); +``` + +#### `Asset.entryUrl()` + +`Asset.entryUrl()`方法可以获得该资源用于 API 调用时所需的 EncodedEntryURL。 +但是在 Node.js SDK 中,大部分 API 都不需要开发者自行使用。:) + +```js +var encodedPicUrl = picture.entryUrl(); +``` + +#### `Asset.stat()` + +Asset.stat 方法可以获得该资源的如文件大小、MIME 类型等 stat 数据。 + +```js +picture.stat(function(err, stat) { + if (err) { + return console.error(err); + } + + console.dir(stat); + /** + * { + * hash : , // string 类型,文件的Hash值 + * fsize : , // int 类型,文件的大小(单位: 字节) + * mimeType : , // string 类型,文件的媒体类型,比如"image/gif" + * putTime : // int64 类型,文件上传到七牛云的时间(Unix时间戳) + * } + */ +}); +``` + +#### `Asset.move()` + +`Asset.move()`方法用于移动该资源到指定的位置。 +第一个参数可以是来自其他 Bucket 所属的资源对象。 + +```js +picture.move(imagesBucket.key('exampleKey_4'), function(err) { + if (err) { + return console.error(err); + } + + // 此处没有返回值,如果没有错误,则为操作成功,以下方法相同 +}); +``` + +#### `Asset.copy()` + +`Asset.copy()`方法用于为该资源创建一个拷贝,并保存到指定的资源位置。 + +```js +imagesBucket.key('exampleKey_4').copy(picture, function(err) { + if (err) { + return console.error(err); + } +}); +``` + +#### `Asset.remove()` + +`Asset.remove()`方法用于删除当前资源。 + +```js +imagesBucket.key('exampleKey_4').remove(function(err) { + if (err) { + return console.error(err); + } +}); +``` + +#### `Asset.token()` + +`Asset.token()`方法用于生成当前资源的下载凭证。 + +```js +var getToken = imagesBucket.key('exampleKey').token(); + +console.dir(getToken); +/*=> + { + url: '', + token: '', + requestUrl: 'URL without token' + } + */ + } +``` + +#### `Asset.download()` + +`Asset.download()`方法用于生成当前资源的下载链接。(不包含下载凭证) + +```js +var url = imagesBucket.key('exampleKey').download(); +``` + +### `Batch` 资源批量操作 + +在支持对单个文件资源操作的同时,七牛云存储还支持批量地对多个文件进行查看、删除、复制和移动操作。 +详细请看:http://docs.qiniu.com/api/v6/rs.html#batch + +生成一个批量操作的控制器 +```js +var batch = qiniu.batch(); +``` + +`Batch`中大部分参数与资源对象`Asset`类似,支持查看、移动、复制和删除操作。 + +```js +batch + // 获取文件信息 + .stat(imagesBucket.key('exampleKey')) + // 移动资源 + .move(imagesBucket.key('exampleKey'), imagesBucket.key('exampleKey_5')) + // 复制资源 + .copy(imagesBucket.key('exampleKey_5'), imagesBucket.key('exampleKey')) + // 删除资源 + .remove(imagesBucket.key('exampleKey_5')) + // 执行操作 + // 每一个操作都按照前后顺序进行执行 + .exec(function(err, results) { + if (err) { + return console.error(err); + } + + console.dir(results); + // results 为每一个操作的结果 + }); +``` + +### `Fop` 管道操作 + +七牛云存储提供一个非常实用的资源处理 API,可以用于对资源进行多种处理的操作。 + +例: 将一个原图缩略,然后在缩略图上打上另外一个图片作为水印 + +使用`Asset.fop()`方法创建 Fop 管道操作器,并进行操作。 + +```js +var image = imagesBucket.key('exampleKey'); +// Image.fop 方法继承于 Asset 类 + +image.fop() + // 对图片进行缩略 + .imageView({ + mode : 2, + height : 200 + }) + // 为图片打上水印 + .watermark({ + mode : 1, + image : 'http://www.b1.qiniudn.com/images/logo-2.png' + }) + // 执行操作 + .exec(function(err, imageData) { + if (err) { + return console.error(err); + } + + // imageData 为已打上水印的缩略图数据 + }); +``` + +#### `Fop.token()` + +该方法用于生成当前 Fop 的下载凭证。 + +```js +var image = imagesBucket.key('exampleKey'); +// Image.fop 方法继承于 Asset 类 + +var getToken = image.fop() + // 对图片进行缩略 + .imageView({ + mode : 2, + height : 200 + }) + // 为图片打上水印 + .watermark({ + mode : 1, + image : 'http://www.b1.qiniudn.com/images/logo-2.png' + }) + .token(); + +console.log(getToken.url); +``` + +## 模块结构 +![模块结构](http://ww2.sinaimg.cn/large/7287333fgw1e8263cvxeaj20mr0glgmp.jpg) + +## License + + (The MIT License) + + Copyright (c) 2010-2013 Will Wen Gunn and other contributors + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + 'Software'), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/example.js b/example.js index aeedc71..b408d54 100644 --- a/example.js +++ b/example.js @@ -1,304 +1,304 @@ -// 引入七牛 Node.js SDK -var qiniu = require('qiniu'); -var fs = require('fs'); - -// 设置全局参数,包括必须的 AccessKey 和 SecretKey, -// 还可以设置其他如 CallbackURL 等参数,将会顺延至所有空间。 -qiniu.config({ - access_key: '------', - secret_key: '------' -}); - -// 获得空间对象 -var imagesBucket = qiniu.bucket('qiniu-sdk-test'); -// 也可以这样操作 -// var imagesBucket = new qiniu.Bucket('qiniu-sdk-test'); - -// 上传一个文件,参数为将要上传的 Key,文件地址(可以是绝对地址,也可以是相对地址), -// 第三个为可选参数 options,即本次上传中所使用 PutToken 的特殊设置, -// 第四个为可选参数回调(callback), -// 若不传入回调函数,将由 putFile 函数所返回的 Promise 对象进行响应。 -imagesBucket.putFile('exampleKey', __dirname + '/assets/example.jpg', function(err, reply) { - if (err) { - return console.error(err); - } - - console.dir(reply); -}); -imagesBucket.putFile('exampleKey_1', __dirname + '/assets/example.jpg', { - // 为本次上传中所使用的 Token 进行设置,此处为设置上传者标识 - endUser: 'foobar' -}, function(err, reply) { - if (err) { - return console.error(err); - } - - console.dir(reply); -}); -// 七牛 Node.js SDK 所提供的 Promise 对象遵循 Promise/A(+) 标准,使用 .then 方法进行响应 -imagesBucket.putFile('exampleKey_2', __dirname + '/assets/example.jpg') - .then( - function(reply) { - // 上传成功 - console.dir(reply); - }, - function(err) { - // 上传失败 - console.error(err); - } - ); - -// 七牛 Node.js SDK 提供基于流(Stream)的操作方式, -// 为熟悉 Node.js 流式操作的开发者提供方便快捷的高性能 API -var puttingStream = imagesBucket.createPutStream('exampleKey_3'); -var readingStream = fs.createReadStream(__dirname + '/assets/example.jpg'); - -readingStream.pipe(readingStream) - .on('error', function(err) { - console.error(err); - }) - .on('end', function(reply) { - console.dir(reply); - }); - -// 获取文件与上传文件同样简单,和 Node.js 中原生的文件系统(File System)的 API 有相似之处 -imagesBucket.getFile('exampleKey', function(err, data) { - if (err) { - return console.error(err); - } - - // data 为包含文件数据的 Buffer 对象 -}); -// 同样的,获取文件也可以使用流式操作进行 -var gettingStream = imagesBucket.createGetStream('exampleKey'); -var writingStream = fs.createWriteStream(__dirname + '/assets/example_tmp.jpg'); - -gettingStream.pipe(writingStream) - .on('error', function(err) { - console.error(err); - }) - .on('finish', function() { - // 文件数据已写入本地文件系统 - }); - -// 图片处理 -// 使用 Bucket.image 方法获取一个图像对象 -var image = imagesBucket.image('exampleKey'); - -// Image.imageInfo 方法可以用于获取图片资源的图片信息 -// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageInfo -image.imageInfo(function(err, info) { - if (err) { - return console.error(err); - } - - console.dir(info); -}); - -// Image.exif 方法可以用于获取图片资源的EXIF信息, -// 前提是该图片由数码相机生成,并且没有清除EXIF信息 -// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageExif -image.exif(function(err, exif) { - if (err) { - return console.error(err); - } - - console.dir(exif); -}); - -// Image.imageView 方法用于生成指定规格的缩略图 -// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageView -image.imageView({ - mode : 2, - width : 180, - height : 180, - quality : 85, - format : 'jpg' -}, function(err, imageData) { - if (err) { - return console.error(err); - } - - // imageData 为处理过后的图像数据 -}); - -// 其中,图片对象中的所有含图片数据返回的方法可以使用流式操作 -// 不传入第二个的 callback 参数,而在调用方法的括弧后再调用 .stream 方法, -// 则会返回一个会不断输出数据的 IO 流 -var imageViewStream = image.imageView({ - mode : 2, - width : 180, - height : 180, - quality : 85, - format : 'jpg' -}).stream(); -var writingStream = fs.createWriteStream(__dirname + '/assets/example_thumbnail.jpg'); - -imageViewStream.pipe(writingStream) - .on('error', function(err) { - console.error(err); - }) - .on('finish', function() { - // 缩略图已写入本地文件系统 - }); - -/** - * 诸如此类: - * image.imageMogr(...).stream(); - * image.watermark(...).stream(); - * image.alias(...).stream(); - */ - -// Image.imageMogr 方法用于调用高级图像处理接口,并返回处理后的图片数据 -// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageMogr -image.imageMogr({ - thumbnail : '300x500', - gravity : 'NorthWest', - crop : '!300x400a10a10', - quality : 85, - rotate : 90, - format : 'jpg' -}, function(err, imageData) { - if (err) { - return console.error(err); - } - - // 使用 imageData 进行操作 -}); - -// Image.watermark 方法用于生成一个带有水印的图片 -// 图片水印 API 支持图片水印和文字水印两种模式 -// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#watermark -image.watermark({ - mode: 1, - image: 'http://www.b1.qiniudn.com/images/logo-2.png', - dissolve: 70, - gravity: 'SouthEast', - dx: 20, - dy: 20 -}, function(err, imageData) { - if (err) { - return console.error(err); - } - - // 使用 imageData 进行操作 -}); - -// Image.alias 方法用于返回既定的数据处理格式的数据 -// 使用此方法需要在 https://portal.qiniu.com 中对设置进行操作 -// PS: Image.alias 方法继承于 key 所用的 Asset 类 -image.alias('testalias', function(err, imageData) { - if (err) { - return console.error(err); - } - - // 使用 imageData 进行操作 -}); - -// 资源操作 -// 获取 key 所对应资源对象 -var picture = imagesBucket.key('exampleKey'); - -// Asset.url 方法可以获得该资源的 URL 地址以用于访问 -var picUrl = picture.url(); - -// Asset.entryUrl 方法可以获得该资源用于 API 调用时所需的 EncodedEntryURL -// 但是在 Node.js SDK 中,大部分 API 都不需要开发者自行使用。:) -var encodedPicUrl = picture.entryUrl(); - -// Asset.stat 方法可以获得该资源的如文件大小、MIME 类型等 stat 数据 -picture.stat(function(err, stat) { - if (err) { - return console.error(err); - } - - console.dir(stat); - /** - * { - * hash : , // string 类型,文件的Hash值 - * fsize : , // int 类型,文件的大小(单位: 字节) - * mimeType : , // string 类型,文件的媒体类型,比如"image/gif" - * putTime : // int64 类型,文件上传到七牛云的时间(Unix时间戳) - * } - */ -}); - -// Asset.move 方法用于移动该资源到指定的位置 -// 第一个参数可以是来自其他 Bucket 所属的资源对象 -picture.move(imagesBucket.key('exampleKey_4'), function(err) { - if (err) { - return console.error(err); - } - - // 此处没有返回值,如果没有错误,则为操作成功,以下方法相同 -}); - -// Asset.copy 方法用于为该资源创建一个拷贝,并保存到指定的资源位置 -imagesBucket.key('exampleKey_4').copy(picture, function(err) { - if (err) { - return console.error(err); - } -}); - -// Asset.remove方法用于删除当前资源 -imagesBucket.key('exampleKey_4').remove(function(err) { - if (err) { - return console.error(err); - } -}); - -// 资源批量操作 -// 在支持对单个文件资源操作的同时,七牛云存储还支持批量地对多个文件进行查看、删除、复制和移动操作。 -// 详细请看:http://docs.qiniu.com/api/v6/rs.html#batch - -// 生成一个批量操作的控制器 -var batch = qiniu.batch(); - -batch - // 获取文件信息 - .stat(imagesBucket.key('exampleKey')) - // 移动资源 - .move(imagesBucket.key('exampleKey'), imagesBucket.key('exampleKey_5')) - // 复制资源 - .copy(imagesBucket.key('exampleKey_5'), imagesBucket.key('exampleKey')) - // 删除资源 - .remove(imagesBucket.key('exampleKey_5')) - // 执行操作 - // 每一个操作都按照前后顺序进行执行 - .exec(function(err, results) { - if (err) { - return console.error(err); - } - - console.dir(results); - // results 为每一个操作的结果 - }); - -// Fop 管道操作 -// 七牛云存储提供一个非常实用的资源处理 API,可以用于对资源进行多种处理的操作 - -// 例: 将一个原图缩略,然后在缩略图上打上另外一个图片作为水印 - -var image = imagesBucket.key('exampleKey'); - -// 使用 Asset.fop 方法创建 Fop 管道操作器 -// Image.fop 方法继承于 Asset 类 -image.fop() - // 对图片进行缩略 - .imageView({ - mode : 2, - height : 200 - }) - // 为图片打上水印 - .watermark({ - mode : 1, - image : 'http://www.b1.qiniudn.com/images/logo-2.png' - }) - // 执行操作 - .exec(function(err, imageData) { - if (err) { - return console.error(err); - } - - // imageData 为已打上水印的缩略图数据 +// 引入七牛 Node.js SDK +var qiniu = require('qiniu'); +var fs = require('fs'); + +// 设置全局参数,包括必须的 AccessKey 和 SecretKey, +// 还可以设置其他如 CallbackURL 等参数,将会顺延至所有空间。 +qiniu.config({ + access_key: '------', + secret_key: '------' +}); + +// 获得空间对象 +var imagesBucket = qiniu.bucket('qiniu-sdk-test'); +// 也可以这样操作 +// var imagesBucket = new qiniu.Bucket('qiniu-sdk-test'); + +// 上传一个文件,参数为将要上传的 Key,文件地址(可以是绝对地址,也可以是相对地址), +// 第三个为可选参数 options,即本次上传中所使用 PutToken 的特殊设置, +// 第四个为可选参数回调(callback), +// 若不传入回调函数,将由 putFile 函数所返回的 Promise 对象进行响应。 +imagesBucket.putFile('exampleKey', __dirname + '/assets/example.jpg', function(err, reply) { + if (err) { + return console.error(err); + } + + console.dir(reply); +}); +imagesBucket.putFile('exampleKey_1', __dirname + '/assets/example.jpg', { + // 为本次上传中所使用的 Token 进行设置,此处为设置上传者标识 + endUser: 'foobar' +}, function(err, reply) { + if (err) { + return console.error(err); + } + + console.dir(reply); +}); +// 七牛 Node.js SDK 所提供的 Promise 对象遵循 Promise/A(+) 标准,使用 .then 方法进行响应 +imagesBucket.putFile('exampleKey_2', __dirname + '/assets/example.jpg') + .then( + function(reply) { + // 上传成功 + console.dir(reply); + }, + function(err) { + // 上传失败 + console.error(err); + } + ); + +// 七牛 Node.js SDK 提供基于流(Stream)的操作方式, +// 为熟悉 Node.js 流式操作的开发者提供方便快捷的高性能 API +var puttingStream = imagesBucket.createPutStream('exampleKey_3'); +var readingStream = fs.createReadStream(__dirname + '/assets/example.jpg'); + +readingStream.pipe(readingStream) + .on('error', function(err) { + console.error(err); + }) + .on('end', function(reply) { + console.dir(reply); + }); + +// 获取文件与上传文件同样简单,和 Node.js 中原生的文件系统(File System)的 API 有相似之处 +imagesBucket.getFile('exampleKey', function(err, data) { + if (err) { + return console.error(err); + } + + // data 为包含文件数据的 Buffer 对象 +}); +// 同样的,获取文件也可以使用流式操作进行 +var gettingStream = imagesBucket.createGetStream('exampleKey'); +var writingStream = fs.createWriteStream(__dirname + '/assets/example_tmp.jpg'); + +gettingStream.pipe(writingStream) + .on('error', function(err) { + console.error(err); + }) + .on('finish', function() { + // 文件数据已写入本地文件系统 + }); + +// 图片处理 +// 使用 Bucket.image 方法获取一个图像对象 +var image = imagesBucket.image('exampleKey'); + +// Image.imageInfo 方法可以用于获取图片资源的图片信息 +// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageInfo +image.imageInfo(function(err, info) { + if (err) { + return console.error(err); + } + + console.dir(info); +}); + +// Image.exif 方法可以用于获取图片资源的EXIF信息, +// 前提是该图片由数码相机生成,并且没有清除EXIF信息 +// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageExif +image.exif(function(err, exif) { + if (err) { + return console.error(err); + } + + console.dir(exif); +}); + +// Image.imageView 方法用于生成指定规格的缩略图 +// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageView +image.imageView({ + mode : 2, + width : 180, + height : 180, + quality : 85, + format : 'jpg' +}, function(err, imageData) { + if (err) { + return console.error(err); + } + + // imageData 为处理过后的图像数据 +}); + +// 其中,图片对象中的所有含图片数据返回的方法可以使用流式操作 +// 不传入第二个的 callback 参数,而在调用方法的括弧后再调用 .stream 方法, +// 则会返回一个会不断输出数据的 IO 流 +var imageViewStream = image.imageView({ + mode : 2, + width : 180, + height : 180, + quality : 85, + format : 'jpg' +}).stream(); +var writingStream = fs.createWriteStream(__dirname + '/assets/example_thumbnail.jpg'); + +imageViewStream.pipe(writingStream) + .on('error', function(err) { + console.error(err); + }) + .on('finish', function() { + // 缩略图已写入本地文件系统 + }); + +/** + * 诸如此类: + * image.imageMogr(...).stream(); + * image.watermark(...).stream(); + * image.alias(...).stream(); + */ + +// Image.imageMogr 方法用于调用高级图像处理接口,并返回处理后的图片数据 +// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#imageMogr +image.imageMogr({ + thumbnail : '300x500', + gravity : 'NorthWest', + crop : '!300x400a10a10', + quality : 85, + rotate : 90, + format : 'jpg' +}, function(err, imageData) { + if (err) { + return console.error(err); + } + + // 使用 imageData 进行操作 +}); + +// Image.watermark 方法用于生成一个带有水印的图片 +// 图片水印 API 支持图片水印和文字水印两种模式 +// 详细请看:http://docs.qiniu.com/api/v6/image-process.html#watermark +image.watermark({ + mode: 1, + image: 'http://www.b1.qiniudn.com/images/logo-2.png', + dissolve: 70, + gravity: 'SouthEast', + dx: 20, + dy: 20 +}, function(err, imageData) { + if (err) { + return console.error(err); + } + + // 使用 imageData 进行操作 +}); + +// Image.alias 方法用于返回既定的数据处理格式的数据 +// 使用此方法需要在 https://portal.qiniu.com 中对设置进行操作 +// PS: Image.alias 方法继承于 key 所用的 Asset 类 +image.alias('testalias', function(err, imageData) { + if (err) { + return console.error(err); + } + + // 使用 imageData 进行操作 +}); + +// 资源操作 +// 获取 key 所对应资源对象 +var picture = imagesBucket.key('exampleKey'); + +// Asset.url 方法可以获得该资源的 URL 地址以用于访问 +var picUrl = picture.url(); + +// Asset.entryUrl 方法可以获得该资源用于 API 调用时所需的 EncodedEntryURL +// 但是在 Node.js SDK 中,大部分 API 都不需要开发者自行使用。:) +var encodedPicUrl = picture.entryUrl(); + +// Asset.stat 方法可以获得该资源的如文件大小、MIME 类型等 stat 数据 +picture.stat(function(err, stat) { + if (err) { + return console.error(err); + } + + console.dir(stat); + /** + * { + * hash : , // string 类型,文件的Hash值 + * fsize : , // int 类型,文件的大小(单位: 字节) + * mimeType : , // string 类型,文件的媒体类型,比如"image/gif" + * putTime : // int64 类型,文件上传到七牛云的时间(Unix时间戳) + * } + */ +}); + +// Asset.move 方法用于移动该资源到指定的位置 +// 第一个参数可以是来自其他 Bucket 所属的资源对象 +picture.move(imagesBucket.key('exampleKey_4'), function(err) { + if (err) { + return console.error(err); + } + + // 此处没有返回值,如果没有错误,则为操作成功,以下方法相同 +}); + +// Asset.copy 方法用于为该资源创建一个拷贝,并保存到指定的资源位置 +imagesBucket.key('exampleKey_4').copy(picture, function(err) { + if (err) { + return console.error(err); + } +}); + +// Asset.remove方法用于删除当前资源 +imagesBucket.key('exampleKey_4').remove(function(err) { + if (err) { + return console.error(err); + } +}); + +// 资源批量操作 +// 在支持对单个文件资源操作的同时,七牛云存储还支持批量地对多个文件进行查看、删除、复制和移动操作。 +// 详细请看:http://docs.qiniu.com/api/v6/rs.html#batch + +// 生成一个批量操作的控制器 +var batch = qiniu.batch(); + +batch + // 获取文件信息 + .stat(imagesBucket.key('exampleKey')) + // 移动资源 + .move(imagesBucket.key('exampleKey'), imagesBucket.key('exampleKey_5')) + // 复制资源 + .copy(imagesBucket.key('exampleKey_5'), imagesBucket.key('exampleKey')) + // 删除资源 + .remove(imagesBucket.key('exampleKey_5')) + // 执行操作 + // 每一个操作都按照前后顺序进行执行 + .exec(function(err, results) { + if (err) { + return console.error(err); + } + + console.dir(results); + // results 为每一个操作的结果 + }); + +// Fop 管道操作 +// 七牛云存储提供一个非常实用的资源处理 API,可以用于对资源进行多种处理的操作 + +// 例: 将一个原图缩略,然后在缩略图上打上另外一个图片作为水印 + +var image = imagesBucket.key('exampleKey'); + +// 使用 Asset.fop 方法创建 Fop 管道操作器 +// Image.fop 方法继承于 Asset 类 +image.fop() + // 对图片进行缩略 + .imageView({ + mode : 2, + height : 200 + }) + // 为图片打上水印 + .watermark({ + mode : 1, + image : 'http://www.b1.qiniudn.com/images/logo-2.png' + }) + // 执行操作 + .exec(function(err, imageData) { + if (err) { + return console.error(err); + } + + // imageData 为已打上水印的缩略图数据 }); \ No newline at end of file diff --git a/lib/batch.js b/lib/batch.js index 8dcf9db..9335faa 100644 --- a/lib/batch.js +++ b/lib/batch.js @@ -1,142 +1,142 @@ -var request = require('request'); -var Q = require('q'); -var _ = require('underscore'); -var util = require('util'); -var url = require('url'); -var http = require('http'); -var utils = require('./utils'); -var config = require('./config'); - -/** - * multiple assets control - * @param {Object} _config config - */ -function Batch(_config) { - this.config = _.extend(_.clone(config), _config); - - var token = require('./token')(this.config); - var AccessToken = token.AccessToken; - - this.access_token = new AccessToken(); - this.op = ''; -} - -/** - * Queue a stat control - * @param {Asset} asset asset - * @return {Batch} Batch - */ -Batch.prototype.stat = function(asset) { - this.op += '&' + genOpUrl('stat', asset); - - return this; -}; - -/** - * Queue a move control - * @param {Asset} src source asset - * @param {Asset} dest dest asset - * @return {Batch} Batch - */ -Batch.prototype.move = function(src, dest) { - this.op += '&' + genOpUrl('move', src, dest); - - return this; -}; - -/** - * Queue a copy control - * @param {Asset} src source asset - * @param {Asset} dest dest asset - * @return {Batch} Batch - */ -Batch.prototype.copy = function(src, dest) { - this.op += '&' + genOpUrl('copy', src, dest); - - return this; -}; - -/** - * Queue a delete control - * @param {Asset} asset asset - * @return {Batch} Batch - */ -Batch.prototype.remove = function(asset) { - this.op += '&' + genOpUrl('delete', asset); - - return this; -}; - -/** - * Execute the queue - * @param {Function} callback Callback - * @return {Promise} promise object - */ -Batch.prototype.exec = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var _url = url.format({ - protocol: 'http', - hostname: this.config.rsUrl, - pathname: '/batch' - }); - var body = this.op.substr(1); - var token = this.access_token.token('/batch', body); - - request({ - url: _url, - method: 'POST', - body: body, - headers: { - 'Authorization': token, - 'Content-Type': 'application/x-www-form-urlencoded' - }, - }, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } - - if (body.length > 0) { - var rows = JSON.parse(body); - - deferred.resolve(rows); - callback(null, rows); - } else { - err = new Error(http.STATUS_CODES[503]); - - deferred.reject(err); - callback(err); - } - }); - - return deferred.promise; -}; - -module.exports = Batch; - -function genOpUrl(op, src, dest) { - var rtn = null; - - switch (op) { - case 'stat': - rtn = util.format('op=/stat/%s', src.entryUrl()); - break; - case 'move': - rtn = util.format('op=/move/%s/%s', src.entryUrl(), dest.entryUrl()); - break; - case 'copy': - rtn = util.format('op=/copy/%s/%s', src.entryUrl(), dest.entryUrl()); - break; - case 'delete': - rtn = util.format('op=/delete/%s', src.entryUrl()); - break; - } - - return rtn; -} - -function noop() { - return false; +var request = require('request'); +var Q = require('q'); +var _ = require('underscore'); +var util = require('util'); +var url = require('url'); +var http = require('http'); +var utils = require('./utils'); +var config = require('./config'); + +/** + * multiple assets control + * @param {Object} _config config + */ +function Batch(_config) { + this.config = _.extend(_.clone(config), _config); + + var token = require('./token')(this.config); + var AccessToken = token.AccessToken; + + this.access_token = new AccessToken(); + this.op = ''; +} + +/** + * Queue a stat control + * @param {Asset} asset asset + * @return {Batch} Batch + */ +Batch.prototype.stat = function(asset) { + this.op += '&' + genOpUrl('stat', asset); + + return this; +}; + +/** + * Queue a move control + * @param {Asset} src source asset + * @param {Asset} dest dest asset + * @return {Batch} Batch + */ +Batch.prototype.move = function(src, dest) { + this.op += '&' + genOpUrl('move', src, dest); + + return this; +}; + +/** + * Queue a copy control + * @param {Asset} src source asset + * @param {Asset} dest dest asset + * @return {Batch} Batch + */ +Batch.prototype.copy = function(src, dest) { + this.op += '&' + genOpUrl('copy', src, dest); + + return this; +}; + +/** + * Queue a delete control + * @param {Asset} asset asset + * @return {Batch} Batch + */ +Batch.prototype.remove = function(asset) { + this.op += '&' + genOpUrl('delete', asset); + + return this; +}; + +/** + * Execute the queue + * @param {Function} callback Callback + * @return {Promise} promise object + */ +Batch.prototype.exec = function(callback) { + var deferred = Q.defer(); + callback = callback || noop; + + var _url = url.format({ + protocol: 'http', + hostname: this.config.rsUrl, + pathname: '/batch' + }); + var body = this.op.substr(1); + var token = this.access_token.token('/batch', body); + + request({ + url: _url, + method: 'POST', + body: body, + headers: { + 'Authorization': token, + 'Content-Type': 'application/x-www-form-urlencoded' + }, + }, function(err, res, body) { + if (err) { + deferred.reject(err); + return callback(err); + } + + if (body.length > 0) { + var rows = JSON.parse(body); + + deferred.resolve(rows); + callback(null, rows); + } else { + err = new Error(http.STATUS_CODES[503]); + + deferred.reject(err); + callback(err); + } + }); + + return deferred.promise; +}; + +module.exports = Batch; + +function genOpUrl(op, src, dest) { + var rtn = null; + + switch (op) { + case 'stat': + rtn = util.format('op=/stat/%s', src.entryUrl()); + break; + case 'move': + rtn = util.format('op=/move/%s/%s', src.entryUrl(), dest.entryUrl()); + break; + case 'copy': + rtn = util.format('op=/copy/%s/%s', src.entryUrl(), dest.entryUrl()); + break; + case 'delete': + rtn = util.format('op=/delete/%s', src.entryUrl()); + break; + } + + return rtn; +} + +function noop() { + return false; } \ No newline at end of file diff --git a/lib/bucket.js b/lib/bucket.js index 43962f8..2435ba1 100644 --- a/lib/bucket.js +++ b/lib/bucket.js @@ -3,10 +3,10 @@ var _ = require('underscore'); var fs = require('fs'); var path = require('path'); var Q = require('q'); -var dataStream = require('dataStream'); var util = require('util'); var url = require('url'); var path = require('path'); +var stream = require('stream'); var Asset = require('./asset'); var Image = require('./image'); var token = null; @@ -122,8 +122,12 @@ Bucket.prototype.createPutStream = function(key, options) { // token var putToken = (new token.PutPolicy(config)).token(); - var stream = new dataStream(); + var _stream = new stream.Transform(); + _stream._transform = function(chunk, encoding, cb) { + cb(null); + }; + // upload API var uploadUrl = url.format({ protocol: 'http', @@ -135,10 +139,10 @@ Bucket.prototype.createPutStream = function(key, options) { var result = JSON.parse(body); if (err) { - return stream.emit('error', err); + return _stream.emit('error', err); } - stream.emit('complete', result); + _stream.emit('end', result); }); // form data @@ -146,18 +150,18 @@ Bucket.prototype.createPutStream = function(key, options) { form.append('token', putToken); form.append('key', key); - stream.on('pipe', function(src) { + _stream.on('pipe', function(src) { if (src.path) { var filename = path.basename(src.path); } else { var filename = key; } - form.append('file', stream, { + form.append('file', _stream, { filename: filename }); }); - return stream; + return _stream; }; /** @@ -173,15 +177,17 @@ Bucket.prototype.getFile = function(key, callback) { callback = callback || noop; var res = request(getToken.url); - var recive = new dataStream(); - res.pipe(recive) - .on('error', deferred.reject.bind(deferred)) - .on('complete', function() { - var data = this.body(); + var recive = new stream.Transform(); + recive._transform = function(chunk, encoding, cb) { + cb(); + }; + recive._flush = function(cb) { + callback(); + cb(); + }; - deferred.resolve(data); - callback(null, data); - }); + res.pipe(recive) + .on('error', deferred.reject.bind(deferred)); return deferred.promise; }; diff --git a/lib/config.js b/lib/config.js index cb0ff9a..a0b3393 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,5 +1,5 @@ -module.exports = { - uploadUrl : 'up.qiniu.com', - rsUrl : 'rs.qbox.me', - rsfUrl : 'rsf.qbox.me' +module.exports = { + uploadUrl : 'up.qiniu.com', + rsUrl : 'rs.qbox.me', + rsfUrl : 'rsf.qbox.me' }; \ No newline at end of file diff --git a/lib/image.js b/lib/image.js index 2beebd9..b0be4f4 100644 --- a/lib/image.js +++ b/lib/image.js @@ -1,268 +1,268 @@ -var request = require('request'); -var _ = require('underscore'); -var fs = require('fs'); -var path = require('path'); -var Q = require('q'); -var dataStream = require('dataStream'); -var util = require('util'); -var url = require('url'); -var Asset = require('./asset'); -var utils = require('./utils'); - -/** - * Image Asset - * @param {String} key key - * @param {Bucket} parent bucket object - */ -function Image(key, parent, _config) { - Image.super_.apply(this, arguments); - - var config = _.extend(_.clone(parent.config), { - separate: '-' - }, _config); - - this.key = key; - this.parent = parent; - this.config = config; -} -util.inherits(Image, Asset); - -/** - * get the image's infomations - * @param {Function} callback Callback - * @return {Promise} promise object - */ -Image.prototype.imageInfo = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var getToken = this.token({ - fop: 'imageInfo' - }); - - var _url = getToken.url + '&token=' + getToken.token; - - request(_url, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } - - var info = JSON.parse(body); - - deferred.resolve(info); - callback(null, info); - }); - - return deferred.promise; -}; - -/** - * get the exif infomation of the picture - * @param {Function} callback Callback - * @return {Promise} promise object - */ -Image.prototype.exif = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var getToken = this.token({ - fop: 'exif' - }); - - var _url = getToken.url + '&token=' + getToken.token; - - request(_url, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } - - var info = JSON.parse(body); - - deferred.resolve(info); - callback(null, info); - }); - - return deferred.promise; -}; - -var imageViewTranslations = { - weight: 'w', - height: 'h', - quality: 'q' -}; - -/** - * return a thumbnail image - * @param {Object} opts options - * @param {Function} callback Callback - * @return {Promise} promise object - */ -Image.prototype.imageView = function(opts, callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var mode = opts.mode; - delete opts.mode; - - var params = {}; - - _.each(opts, function(value, key) { - if (imageViewTranslations.hasOwnProperty(key)) { - key = imageViewTranslations[key]; - } - - params[key] = value; - }); - - var fop = util.format('imageView/%d%s', mode, genOptUrl(params)); - - var getToken = this.token({ - fop: fop - }); - - var _url = getToken.url + '&token=' + getToken.token; - - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { - deferred.reject(err); - callback(err); - }); - - - var promise = deferred.promise; - - /** - * return the image stream - * @return {Stream} stream - */ - promise.stream = function() { - return recive; - }; - - return promise; -}; - -/** - * return a processed image - * @param {Object} opts options - * @param {Function} callback Callback - * @return {Promise} promise object - */ -Image.prototype.imageMogr = function(opts, callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var params = {}; - - _.extend(params, opts); - - var fop = util.format('imageMogr/v2/auto-orient%s', genOptUrl(params)); - - var getToken = this.token({ - fop: fop - }); - - var _url = getToken.url + '&token=' + getToken.token; - - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { - deferred.reject(err); - callback(err); - }); - - var promise = deferred.promise; - - /** - * return the image stream - * @return {Stream} stream - */ - promise.stream = function() { - return recive; - }; - - return promise; -}; - -/** - * return a image with a watermark - * @param {Object} opts options - * @param {Function} callback Callback - * @return {Promise} promise object - */ -Image.prototype.watermark = function(opts, callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var params = {}; - var mode = opts.mode; - delete opts.mode; - - _.extend(params, opts); - - params.image = utils.safeEncode(params.image); - - var fop = util.format('watermark/%d%s', mode, genOptUrl(params)); - - var getToken = this.token({ - fop: fop - }); - - var _url = getToken.url + '&token=' + getToken.token; - - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { - deferred.reject(err); - callback(err); - }); - - var promise = deferred.promise; - - /** - * return the image stream - * @return {Stream} stream - */ - promise.stream = function() { - return recive; - }; - - return promise; -}; - -module.exports = Image; - -function genOptUrl(params) { - var _url = ""; - - _.each(params, function(value, key) { - _url += util.format('/%s/%s', key, value); - }); - - return _url; -} - -function noop() { - return false; +var request = require('request'); +var _ = require('underscore'); +var fs = require('fs'); +var path = require('path'); +var Q = require('q'); +var dataStream = require('dataStream'); +var util = require('util'); +var url = require('url'); +var Asset = require('./asset'); +var utils = require('./utils'); + +/** + * Image Asset + * @param {String} key key + * @param {Bucket} parent bucket object + */ +function Image(key, parent, _config) { + Image.super_.apply(this, arguments); + + var config = _.extend(_.clone(parent.config), { + separate: '-' + }, _config); + + this.key = key; + this.parent = parent; + this.config = config; +} +util.inherits(Image, Asset); + +/** + * get the image's infomations + * @param {Function} callback Callback + * @return {Promise} promise object + */ +Image.prototype.imageInfo = function(callback) { + var deferred = Q.defer(); + callback = callback || noop; + + var getToken = this.token({ + fop: 'imageInfo' + }); + + var _url = getToken.url + '&token=' + getToken.token; + + request(_url, function(err, res, body) { + if (err) { + deferred.reject(err); + return callback(err); + } + + var info = JSON.parse(body); + + deferred.resolve(info); + callback(null, info); + }); + + return deferred.promise; +}; + +/** + * get the exif infomation of the picture + * @param {Function} callback Callback + * @return {Promise} promise object + */ +Image.prototype.exif = function(callback) { + var deferred = Q.defer(); + callback = callback || noop; + + var getToken = this.token({ + fop: 'exif' + }); + + var _url = getToken.url + '&token=' + getToken.token; + + request(_url, function(err, res, body) { + if (err) { + deferred.reject(err); + return callback(err); + } + + var info = JSON.parse(body); + + deferred.resolve(info); + callback(null, info); + }); + + return deferred.promise; +}; + +var imageViewTranslations = { + weight: 'w', + height: 'h', + quality: 'q' +}; + +/** + * return a thumbnail image + * @param {Object} opts options + * @param {Function} callback Callback + * @return {Promise} promise object + */ +Image.prototype.imageView = function(opts, callback) { + var deferred = Q.defer(); + callback = callback || noop; + + var mode = opts.mode; + delete opts.mode; + + var params = {}; + + _.each(opts, function(value, key) { + if (imageViewTranslations.hasOwnProperty(key)) { + key = imageViewTranslations[key]; + } + + params[key] = value; + }); + + var fop = util.format('imageView/%d%s', mode, genOptUrl(params)); + + var getToken = this.token({ + fop: fop + }); + + var _url = getToken.url + '&token=' + getToken.token; + + var recive = new dataStream(); + request(_url).pipe(recive) + .on('complete', function() { + var data = this.body(); + + deferred.resolve(data); + callback(null, data); + }) + .on('error', function(err) { + deferred.reject(err); + callback(err); + }); + + + var promise = deferred.promise; + + /** + * return the image stream + * @return {Stream} stream + */ + promise.stream = function() { + return recive; + }; + + return promise; +}; + +/** + * return a processed image + * @param {Object} opts options + * @param {Function} callback Callback + * @return {Promise} promise object + */ +Image.prototype.imageMogr = function(opts, callback) { + var deferred = Q.defer(); + callback = callback || noop; + + var params = {}; + + _.extend(params, opts); + + var fop = util.format('imageMogr/v2/auto-orient%s', genOptUrl(params)); + + var getToken = this.token({ + fop: fop + }); + + var _url = getToken.url + '&token=' + getToken.token; + + var recive = new dataStream(); + request(_url).pipe(recive) + .on('complete', function() { + var data = this.body(); + + deferred.resolve(data); + callback(null, data); + }) + .on('error', function(err) { + deferred.reject(err); + callback(err); + }); + + var promise = deferred.promise; + + /** + * return the image stream + * @return {Stream} stream + */ + promise.stream = function() { + return recive; + }; + + return promise; +}; + +/** + * return a image with a watermark + * @param {Object} opts options + * @param {Function} callback Callback + * @return {Promise} promise object + */ +Image.prototype.watermark = function(opts, callback) { + var deferred = Q.defer(); + callback = callback || noop; + + var params = {}; + var mode = opts.mode; + delete opts.mode; + + _.extend(params, opts); + + params.image = utils.safeEncode(params.image); + + var fop = util.format('watermark/%d%s', mode, genOptUrl(params)); + + var getToken = this.token({ + fop: fop + }); + + var _url = getToken.url + '&token=' + getToken.token; + + var recive = new dataStream(); + request(_url).pipe(recive) + .on('complete', function() { + var data = this.body(); + + deferred.resolve(data); + callback(null, data); + }) + .on('error', function(err) { + deferred.reject(err); + callback(err); + }); + + var promise = deferred.promise; + + /** + * return the image stream + * @return {Stream} stream + */ + promise.stream = function() { + return recive; + }; + + return promise; +}; + +module.exports = Image; + +function genOptUrl(params) { + var _url = ""; + + _.each(params, function(value, key) { + _url += util.format('/%s/%s', key, value); + }); + + return _url; +} + +function noop() { + return false; } \ No newline at end of file diff --git a/lib/token.js b/lib/token.js index d228b21..29a2067 100644 --- a/lib/token.js +++ b/lib/token.js @@ -1,115 +1,115 @@ -/** - * Qiniu Token generic - */ - -var _ = require('underscore'); -var util = require('util'); -var url = require('url'); -var qs = require('querystring'); -var utils = require('./utils'); - -var globalConfig = null; - -/** - * Put Policy - * @param {Object} opts options - */ -function PutPolicy(opts) { - var now = Math.floor(Date.now() / 1000); - - this.scope = opts.scope || null; - this.deadline = now + opts.deadline || now + 3600; - this.endUser = opts.endUser || null; - this.returnUrl = opts.returnUrl || null; - this.returnBody = opts.returnBody || null; - this.callbackUrl = opts.callbackUrl || null; - this.callbackBody = opts.callbackBody || null; - this.asyncOps = opts.asyncOps || null; -} - -/** - * Generate the token - * @return {String} token - */ -PutPolicy.prototype.token = function() { - var params = {}; - - _.each(this, function(value, key) { - if (!_.isNull(value)) { - params[key] = value; - } - }); - return generateToken(params); -}; - -function generateToken(params) { - // signature - var signature = utils.safeEncode(JSON.stringify(params)); - - // EncodedDigest - var encodedDigest = utils.encodeSign(signature, globalConfig.secret_key); - - return util.format('%s:%s:%s', globalConfig.access_key, encodedDigest, signature) -} - -function GetPolicy(opts) { - opts = opts || {}; - var now = Math.floor(Date.now() / 1000); - - this.deadline = now + opts.deadline || now + 3600; -} - -GetPolicy.prototype.token = function(domain, key, opts) { - opts = opts || {}; - var fop = opts.fop || 'e'; - var base = ''; - - if (_.isUndefined(key)) { - // base url - var encodedDigest = utils.encodeSign(domain, globalConfig.secret_key); - } else { - // safe domain - var hostname = url.parse(domain).hostname; - - base = url.format({ - protocol: 'http', - hostname: hostname, - pathname: key - }); - - base += '?' + encodeURIComponent(fop); - base += '&' + qs.stringify({ - e: this.deadline - }); - - var encodedDigest = utils.encodeSign(base, globalConfig.secret_key); - } - - var token = util.format('%s:%s', globalConfig.access_key, encodedDigest); - - return { - token: token, - requestUrl: base, - url: base + '&token=' + token - }; -}; - -function AccessToken() {} - -AccessToken.prototype.token = function(path, body) { - body = body || ''; - - var data = util.format('%s\n%s', path, body); - - var encodeSignData = utils.encodeSign(data, globalConfig.secret_key); - - return util.format('QBox %s:%s', globalConfig.access_key, encodeSignData); -}; -module.exports = function(config) { - globalConfig = config; - return { - PutPolicy: PutPolicy, - GetPolicy: GetPolicy, - AccessToken: AccessToken - }; +/** + * Qiniu Token generic + */ + +var _ = require('underscore'); +var util = require('util'); +var url = require('url'); +var qs = require('querystring'); +var utils = require('./utils'); + +var globalConfig = null; + +/** + * Put Policy + * @param {Object} opts options + */ +function PutPolicy(opts) { + var now = Math.floor(Date.now() / 1000); + + this.scope = opts.scope || null; + this.deadline = now + opts.deadline || now + 3600; + this.endUser = opts.endUser || null; + this.returnUrl = opts.returnUrl || null; + this.returnBody = opts.returnBody || null; + this.callbackUrl = opts.callbackUrl || null; + this.callbackBody = opts.callbackBody || null; + this.asyncOps = opts.asyncOps || null; +} + +/** + * Generate the token + * @return {String} token + */ +PutPolicy.prototype.token = function() { + var params = {}; + + _.each(this, function(value, key) { + if (!_.isNull(value)) { + params[key] = value; + } + }); + return generateToken(params); +}; + +function generateToken(params) { + // signature + var signature = utils.safeEncode(JSON.stringify(params)); + + // EncodedDigest + var encodedDigest = utils.encodeSign(signature, globalConfig.secret_key); + + return util.format('%s:%s:%s', globalConfig.access_key, encodedDigest, signature) +} + +function GetPolicy(opts) { + opts = opts || {}; + var now = Math.floor(Date.now() / 1000); + + this.deadline = now + opts.deadline || now + 3600; +} + +GetPolicy.prototype.token = function(domain, key, opts) { + opts = opts || {}; + var fop = opts.fop || 'e'; + var base = ''; + + if (_.isUndefined(key)) { + // base url + var encodedDigest = utils.encodeSign(domain, globalConfig.secret_key); + } else { + // safe domain + var hostname = url.parse(domain).hostname; + + base = url.format({ + protocol: 'http', + hostname: hostname, + pathname: key + }); + + base += '?' + encodeURIComponent(fop); + base += '&' + qs.stringify({ + e: this.deadline + }); + + var encodedDigest = utils.encodeSign(base, globalConfig.secret_key); + } + + var token = util.format('%s:%s', globalConfig.access_key, encodedDigest); + + return { + token: token, + requestUrl: base, + url: base + '&token=' + token + }; +}; + +function AccessToken() {} + +AccessToken.prototype.token = function(path, body) { + body = body || ''; + + var data = util.format('%s\n%s', path, body); + + var encodeSignData = utils.encodeSign(data, globalConfig.secret_key); + + return util.format('QBox %s:%s', globalConfig.access_key, encodeSignData); +}; +module.exports = function(config) { + globalConfig = config; + return { + PutPolicy: PutPolicy, + GetPolicy: GetPolicy, + AccessToken: AccessToken + }; }; \ No newline at end of file diff --git a/lib/utils.js b/lib/utils.js index c1b75ef..2dab1b4 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,20 +1,20 @@ -var crypto = require('crypto'); -var fs = require('fs'); - -var utils = exports; - -utils.safeEncode = function(str) { - var encoded = new Buffer(str).toString('base64'); - var rtn = encoded.replace(/\//g, '_').replace(/\+/g, '-'); - - return rtn; -}; - -utils.encodeSign = function(str, key) { - return utils.safeEncode( - crypto - .createHmac('sha1', key) - .update(str) - .digest() - ); +var crypto = require('crypto'); +var fs = require('fs'); + +var utils = exports; + +utils.safeEncode = function(str) { + var encoded = new Buffer(str).toString('base64'); + var rtn = encoded.replace(/\//g, '_').replace(/\+/g, '-'); + + return rtn; +}; + +utils.encodeSign = function(str, key) { + return utils.safeEncode( + crypto + .createHmac('sha1', key) + .update(str) + .digest() + ); }; \ No newline at end of file diff --git a/package.json b/package.json index 19a4953..73259f2 100644 --- a/package.json +++ b/package.json @@ -1,52 +1,52 @@ -{ - "name": "node-qiniu", - "version": "6.1.6", - "description": "Qiniu Resource Storage SDK for Node.js", - "main": "index.js", - "directories": { - "doc": "doc", - "test": "test" - }, - "scripts": { - "test": "make test", - "blanket": { - "pattern": "node-qiniu/lib", - "data-cover-flags": { - "debug": false - } - }, - "travis-cov": { - "threshold": 88 - } - }, - "repository": { - "type": "git", - "url": "https://www.npmjs.org/package/node-qiniu" - }, - "keywords": [ - "cloud", - "storage", - "s3", - "qiniu", - "web-service" - ], - "author": "iwillwen", - "license": "MIT", - "bugs": { - "url": "https://www.npmjs.org/package/node-qiniu/issues" - }, - "dependencies": { - "underscore": "~1.5.1", - "request": "~2.27.0", - "q": "~0.9.6", - "dataStream": "0.0.5" - }, - "devDependencies": { - "async": "~0.2.9", - "mocha": "~1.6.0", - "should": "~1.2.2", - "doxmate": "*", - "blanket": "*", - "travis-cov": "*" - } -} +{ + "name": "node-qiniu", + "version": "6.1.6", + "description": "Qiniu Resource Storage SDK for Node.js", + "main": "index.js", + "directories": { + "doc": "doc", + "test": "test" + }, + "scripts": { + "test": "make test", + "blanket": { + "pattern": "node-qiniu/lib", + "data-cover-flags": { + "debug": false + } + }, + "travis-cov": { + "threshold": 88 + } + }, + "repository": { + "type": "git", + "url": "https://www.npmjs.org/package/node-qiniu" + }, + "keywords": [ + "cloud", + "storage", + "s3", + "qiniu", + "web-service" + ], + "author": "iwillwen", + "license": "MIT", + "bugs": { + "url": "https://www.npmjs.org/package/node-qiniu/issues" + }, + "dependencies": { + "bufferhelper": "^0.2.0", + "q": "~0.9.6", + "request": "~2.27.0", + "underscore": "~1.5.1" + }, + "devDependencies": { + "async": "~0.2.9", + "mocha": "~1.6.0", + "should": "~1.2.2", + "doxmate": "*", + "blanket": "*", + "travis-cov": "*" + } +} diff --git a/test/index.js b/test/index.js index 7eb0c65..bd5438f 100644 --- a/test/index.js +++ b/test/index.js @@ -1,11 +1,10 @@ -var qiniu = require('../'); - -qiniu.config({ - access_key: '5UyUq-l6jsWqZMU6tuQ85Msehrs3Dr58G-mCZ9rE', - secret_key: 'YaRsPKiYm4nGUt8mdz2QxeV5Q_yaUzVxagRuWTfM' - -}); - -qiniu.testBucket = new qiniu.Bucket('qiniu-sdk-test'); - -module.exports = qiniu; +var qiniu = require('../'); + +qiniu.config({ + access_key: '5UyUq-l6jsWqZMU6tuQ85Msehrs3Dr58G-mCZ9rE', + secret_key: 'YaRsPKiYm4nGUt8mdz2QxeV5Q_yaUzVxagRuWTfM' +}); + +qiniu.testBucket = new qiniu.Bucket('qiniu-sdk-test'); + +module.exports = qiniu; diff --git a/test/qiniu_batch.js b/test/qiniu_batch.js index 2451a86..45a23b7 100644 --- a/test/qiniu_batch.js +++ b/test/qiniu_batch.js @@ -1,64 +1,64 @@ -var qiniu = require('./'); -var assert = require('assert'); - -var bucket = qiniu.testBucket; - -describe('qiniu.Batch', function() { - - describe('Batch.stat()', function() { - it('should get the assets\' stats', function(done) { - qiniu.batch() - .stat(bucket.key('gogopher.jpg')) - .exec(function(err, stat) { - if (err) { - throw err; - } - - done(); - }); - }); - }); - - describe('Batch.move()', function() { - it('should move the asset to another position', function(done) { - qiniu.batch() - .move(bucket.key('gogopher.jpg'), bucket.key('gogopher_tmp.jpg')) - .exec(function(err) { - if (err) { - throw err; - } - - done(); - }); - }); - }); - - describe('Batch.copy()', function() { - it('should make some copies of the assets to the other positions', function(done) { - qiniu.batch() - .move(bucket.key('gogopher_tmp.jpg'), bucket.key('gogopher.jpg')) - .exec(function(err) { - if (err) { - throw err; - } - - done(); - }); - }); - }); - - describe('Batch.remove()', function() { - it('should delete the assets', function(done) { - qiniu.batch() - .remove(bucket.key('gogopher_tmp.jpg')) - .exec(function(err, stat) { - if (err) { - throw err; - } - - done(); - }); - }); - }); - +var qiniu = require('./'); +var assert = require('assert'); + +var bucket = qiniu.testBucket; + +describe('qiniu.Batch', function() { + + describe('Batch.stat()', function() { + it('should get the assets\' stats', function(done) { + qiniu.batch() + .stat(bucket.key('gogopher.jpg')) + .exec(function(err, stat) { + if (err) { + throw err; + } + + done(); + }); + }); + }); + + describe('Batch.move()', function() { + it('should move the asset to another position', function(done) { + qiniu.batch() + .move(bucket.key('gogopher.jpg'), bucket.key('gogopher_tmp.jpg')) + .exec(function(err) { + if (err) { + throw err; + } + + done(); + }); + }); + }); + + describe('Batch.copy()', function() { + it('should make some copies of the assets to the other positions', function(done) { + qiniu.batch() + .move(bucket.key('gogopher_tmp.jpg'), bucket.key('gogopher.jpg')) + .exec(function(err) { + if (err) { + throw err; + } + + done(); + }); + }); + }); + + describe('Batch.remove()', function() { + it('should delete the assets', function(done) { + qiniu.batch() + .remove(bucket.key('gogopher_tmp.jpg')) + .exec(function(err, stat) { + if (err) { + throw err; + } + + done(); + }); + }); + }); + }); \ No newline at end of file diff --git a/test/qiniu_get.js b/test/qiniu_get.js index 1a3827b..d41c4e3 100644 --- a/test/qiniu_get.js +++ b/test/qiniu_get.js @@ -1,35 +1,35 @@ -var qiniu = require('./'); -var fs = require('fs'); -var assert = require('assert'); - -describe('qiniu.Get', function() { - - describe('Bucket.getFile()', function() { - it('should gets a file with giving a pathname', function(done) { - - qiniu.testBucket.getFile('gogopher.jpg', function(err) { - if (err) { - throw err; - } - - done(); - }); - - }); - }); - - describe('Bucket.createGetStream()', function() { - it('should gets a file with a stream', function(done) { - - var gettingStream = qiniu.testBucket.createGetStream('gogopher.jpg'); - var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_tmp.jpg'); - - gettingStream.pipe(writingStream) - .on('error', function(err) { - throw err; - }) - .on('finish', done); - }); - }); - +var qiniu = require('./'); +var fs = require('fs'); +var assert = require('assert'); + +describe('qiniu.Get', function() { + + describe('Bucket.getFile()', function() { + it('should gets a file with giving a pathname', function(done) { + + qiniu.testBucket.getFile('gogopher.jpg', function(err) { + if (err) { + throw err; + } + + done(); + }); + + }); + }); + + describe('Bucket.createGetStream()', function() { + it('should gets a file with a stream', function(done) { + + var gettingStream = qiniu.testBucket.createGetStream('gogopher.jpg'); + var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_tmp.jpg'); + + gettingStream.pipe(writingStream) + .on('error', function(err) { + throw err; + }) + .on('finish', done); + }); + }); + }); \ No newline at end of file diff --git a/test/qiniu_image.js b/test/qiniu_image.js index 096fa1f..6c20744 100644 --- a/test/qiniu_image.js +++ b/test/qiniu_image.js @@ -1,217 +1,217 @@ -var qiniu = require('./'); -var fs = require('fs'); -var dataStream = require('dataStream'); -var assert = require('assert'); - -var image = qiniu.testBucket.image('gogopher.jpg'); - -describe('qiniu.Image', function() { - - describe('Image.imageInfo()', function() { - it('should return some infomations of a picture', function(done) { - - image.imageInfo(function(err, data) { - if (err) { - throw err; - } - - done(); - }); - - }); - }); - - describe('Image.exif()', function() { - it('should return the exif infomation of a picture', function(done) { - - image.exif(function(err) { - if (err) { - throw err; - } - - done(); - }); - - }); - }); - - describe('Image.imageView()', function() { - it('should return a thumbnail image', function(done) { - - // imageView - image.imageView({ - mode : 2, - width : 180, - height : 180, - quality : 85, - format : 'jpg' - }, function(err, thumbnail) { - if (err) { - throw err; - } - - fs.writeFile(__dirname + '/assets/gogopher_thumbnail.jpg', thumbnail, function(err) { - done(); - }); - }); - - }); - }); - - describe('Image.imageView().straem()', function() { - it('should return a thumbnail image by a stream', function(done) { - - // imageView Stream - var imageStream = image.imageView({ - mode : 2, - width : 180, - height : 180, - quality : 85, - format : 'jpg' - }).stream(); - var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_thumbnail.jpg'); - - imageStream.pipe(writingStream) - .on('error', function(err) { - throw err; - }) - .on('finish', function() { - done(); - }); - }); - }); - - describe('Image.imageMogr()', function() { - it('should return a processed image', function(done) { - - // imageMogr - image.imageMogr({ - thumbnail : '300x500', - gravity : 'NorthWest', - crop : '!300x400a10a10', - quality : 85, - rotate : 90, - format : 'jpg' - }, function(err, mogred) { - if (err) { - throw err; - } - - fs.writeFile(__dirname + '/assets/gogopher_mogred.jpg', mogred, function(err) { - done(); - }); - }); - - }); - }); - - describe('Image.imageMogr().stream()', function() { - it('should return a processed image by a stream', function(done) { - - // imageMogr - var imageStream = image.imageMogr({ - thumbnail : '300x500', - gravity : 'NorthWest', - crop : '!300x400a10a10', - quality : 85, - rotate : 90, - format : 'jpg' - }).stream(); - var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_mogred.jpg'); - - imageStream.pipe(writingStream) - .on('error', function(err) { - throw err; - }) - .on('finish', function() { - done(); - }); - - }); - }); - - describe('Image.watermark()', function() { - it('should return a image with a watermark', function(done) { - - // watermarks - image.watermark({ - mode: 1, - image: 'http://www.b1.qiniudn.com/images/logo-2.png', - dissolve: 70, - gravity: 'SouthEast', - dx: 20, - dy: 20 - }, function(err, pic) { - if (err) { - throw err; - } - - fs.writeFile(__dirname + '/assets/gogopher_watermark.jpg', pic, function(err) { - done(); - }); - }); - - }); - }); - - describe('Image.watermark().stream()', function() { - it('should return a image with a watermark by stream', function(done) { - - // watermarks - var imageStream = image.watermark({ - mode: 1, - image: 'http://www.b1.qiniudn.com/images/logo-2.png', - dissolve: 70, - gravity: 'SouthEast', - dx: 20, - dy: 20 - }).stream(); - var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_watermark.jpg'); - - imageStream.pipe(writingStream) - .on('error', function(err) { - throw err; - }) - .on('finish', function() { - done(); - }); - - }); - }); - - describe('Image.alias()', function() { - it('should return a image with a established format', function(done) { - - // watermarks - image.alias('testalias', function(err, pic) { - if (err) { - throw err; - } - - fs.writeFile(__dirname + '/assets/gogopher_alias.jpg', pic, function(err) { - done(); - }); - }); - - }); - }); - - describe('Image.alias().stream()', function() { - it('should return a image with a established format by stream', function(done) { - - // watermarks - var imageStream = image.alias('testalias').stream(); - var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_alias.jpg'); - - imageStream.pipe(writingStream) - .on('error', function(err) { - throw err; - }) - .on('finish', function() { - done(); - }); - - }); - }); - +var qiniu = require('./'); +var fs = require('fs'); +var dataStream = require('dataStream'); +var assert = require('assert'); + +var image = qiniu.testBucket.image('gogopher.jpg'); + +describe('qiniu.Image', function() { + + describe('Image.imageInfo()', function() { + it('should return some infomations of a picture', function(done) { + + image.imageInfo(function(err, data) { + if (err) { + throw err; + } + + done(); + }); + + }); + }); + + describe('Image.exif()', function() { + it('should return the exif infomation of a picture', function(done) { + + image.exif(function(err) { + if (err) { + throw err; + } + + done(); + }); + + }); + }); + + describe('Image.imageView()', function() { + it('should return a thumbnail image', function(done) { + + // imageView + image.imageView({ + mode : 2, + width : 180, + height : 180, + quality : 85, + format : 'jpg' + }, function(err, thumbnail) { + if (err) { + throw err; + } + + fs.writeFile(__dirname + '/assets/gogopher_thumbnail.jpg', thumbnail, function(err) { + done(); + }); + }); + + }); + }); + + describe('Image.imageView().straem()', function() { + it('should return a thumbnail image by a stream', function(done) { + + // imageView Stream + var imageStream = image.imageView({ + mode : 2, + width : 180, + height : 180, + quality : 85, + format : 'jpg' + }).stream(); + var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_thumbnail.jpg'); + + imageStream.pipe(writingStream) + .on('error', function(err) { + throw err; + }) + .on('finish', function() { + done(); + }); + }); + }); + + describe('Image.imageMogr()', function() { + it('should return a processed image', function(done) { + + // imageMogr + image.imageMogr({ + thumbnail : '300x500', + gravity : 'NorthWest', + crop : '!300x400a10a10', + quality : 85, + rotate : 90, + format : 'jpg' + }, function(err, mogred) { + if (err) { + throw err; + } + + fs.writeFile(__dirname + '/assets/gogopher_mogred.jpg', mogred, function(err) { + done(); + }); + }); + + }); + }); + + describe('Image.imageMogr().stream()', function() { + it('should return a processed image by a stream', function(done) { + + // imageMogr + var imageStream = image.imageMogr({ + thumbnail : '300x500', + gravity : 'NorthWest', + crop : '!300x400a10a10', + quality : 85, + rotate : 90, + format : 'jpg' + }).stream(); + var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_mogred.jpg'); + + imageStream.pipe(writingStream) + .on('error', function(err) { + throw err; + }) + .on('finish', function() { + done(); + }); + + }); + }); + + describe('Image.watermark()', function() { + it('should return a image with a watermark', function(done) { + + // watermarks + image.watermark({ + mode: 1, + image: 'http://www.b1.qiniudn.com/images/logo-2.png', + dissolve: 70, + gravity: 'SouthEast', + dx: 20, + dy: 20 + }, function(err, pic) { + if (err) { + throw err; + } + + fs.writeFile(__dirname + '/assets/gogopher_watermark.jpg', pic, function(err) { + done(); + }); + }); + + }); + }); + + describe('Image.watermark().stream()', function() { + it('should return a image with a watermark by stream', function(done) { + + // watermarks + var imageStream = image.watermark({ + mode: 1, + image: 'http://www.b1.qiniudn.com/images/logo-2.png', + dissolve: 70, + gravity: 'SouthEast', + dx: 20, + dy: 20 + }).stream(); + var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_watermark.jpg'); + + imageStream.pipe(writingStream) + .on('error', function(err) { + throw err; + }) + .on('finish', function() { + done(); + }); + + }); + }); + + describe('Image.alias()', function() { + it('should return a image with a established format', function(done) { + + // watermarks + image.alias('testalias', function(err, pic) { + if (err) { + throw err; + } + + fs.writeFile(__dirname + '/assets/gogopher_alias.jpg', pic, function(err) { + done(); + }); + }); + + }); + }); + + describe('Image.alias().stream()', function() { + it('should return a image with a established format by stream', function(done) { + + // watermarks + var imageStream = image.alias('testalias').stream(); + var writingStream = fs.createWriteStream(__dirname + '/assets/gogopher_alias.jpg'); + + imageStream.pipe(writingStream) + .on('error', function(err) { + throw err; + }) + .on('finish', function() { + done(); + }); + + }); + }); + }); \ No newline at end of file diff --git a/test/qiniu_put.js b/test/qiniu_put.js index 15f4a13..c20e219 100644 --- a/test/qiniu_put.js +++ b/test/qiniu_put.js @@ -1,37 +1,37 @@ -var qiniu = require('./'); -var fs = require('fs'); -var assert = require('assert'); - -describe('qiniu.Put', function() { - - describe('Bucket.putFile()', function() { - it('should uploads a file with giving a pathname', function(done) { - - qiniu.testBucket.putFile('gogopher.jpg', __dirname + '/assets/gogopher.jpg', function(err, reply) { - if (err) { - throw err; - } - - done(); - }); - - }); - }); - - describe('Bucket.createPutStream()', function() { - it('should uploads a file with a stream', function(done) { - - var puttingStream = qiniu.testBucket.createPutStream('gogopher.jpg'); - var readingStream = fs.createReadStream(__dirname + '/assets/gogopher.jpg'); - - readingStream.pipe(puttingStream) - .on('error', function(err) { - throw err; - }) - .on('complete', function() { - done(); - }); - }); - }); - +var qiniu = require('./'); +var fs = require('fs'); +var assert = require('assert'); + +describe('qiniu.Put', function() { + + describe('Bucket.putFile()', function() { + it('should uploads a file with giving a pathname', function(done) { + + qiniu.testBucket.putFile('gogopher.jpg', __dirname + '/assets/gogopher.jpg', function(err, reply) { + if (err) { + throw err; + } + + done(); + }); + + }); + }); + + describe('Bucket.createPutStream()', function() { + it('should uploads a file with a stream', function(done) { + + var puttingStream = qiniu.testBucket.createPutStream('gogopher.jpg'); + var readingStream = fs.createReadStream(__dirname + '/assets/gogopher.jpg'); + + readingStream.pipe(puttingStream) + .on('error', function(err) { + throw err; + }) + .on('end', function() { + done(); + }); + }); + }); + }); \ No newline at end of file From e327fd90d14af6144036bd0b3ccdac58adeba002 Mon Sep 17 00:00:00 2001 From: iwillwen Date: Sun, 18 Jan 2015 22:57:58 +0800 Subject: [PATCH 05/10] Removed dataStream and using strea.Transform --- lib/bucket.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/bucket.js b/lib/bucket.js index 2435ba1..78b0bf4 100644 --- a/lib/bucket.js +++ b/lib/bucket.js @@ -207,6 +207,7 @@ Bucket.prototype.createGetStream = function(key) { }; Bucket.prototype.url = function() { + if (this.config.url) return this.config.url; return util.format('%s.qiniudn.com', this.name); }; From ae9e0db2ed36e9340a6307b697da3e692e57654f Mon Sep 17 00:00:00 2001 From: iwillwen Date: Sun, 18 Jan 2015 23:20:22 +0800 Subject: [PATCH 06/10] Removed dataStream and using strea.Transform --- lib/image.js | 57 ++++++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/lib/image.js b/lib/image.js index b0be4f4..b312de2 100644 --- a/lib/image.js +++ b/lib/image.js @@ -4,6 +4,7 @@ var fs = require('fs'); var path = require('path'); var Q = require('q'); var dataStream = require('dataStream'); +var stream = require('stream'); var util = require('util'); var url = require('url'); var Asset = require('./asset'); @@ -124,19 +125,15 @@ Image.prototype.imageView = function(opts, callback) { var _url = getToken.url + '&token=' + getToken.token; - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { + var recive = request(_url, function(err, resp, body) { + if (err) { deferred.reject(err); - callback(err); - }); + return callback(err); + } + deferred.resolve(body); + callback(null, body); + }); var promise = deferred.promise; @@ -173,18 +170,15 @@ Image.prototype.imageMogr = function(opts, callback) { var _url = getToken.url + '&token=' + getToken.token; - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { + var recive = request(_url, function(err, resp, body) { + if (err) { deferred.reject(err); - callback(err); - }); + return callback(err); + } + + deferred.resolve(body); + callback(null, body); + }); var promise = deferred.promise; @@ -225,18 +219,15 @@ Image.prototype.watermark = function(opts, callback) { var _url = getToken.url + '&token=' + getToken.token; - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { + var recive = request(_url, function(err, resp, body) { + if (err) { deferred.reject(err); - callback(err); - }); + return callback(err); + } + + deferred.resolve(body); + callback(null, body); + }); var promise = deferred.promise; From d82436ea22026f13dd461351da0d58bfec1d54b9 Mon Sep 17 00:00:00 2001 From: iwillwen Date: Sun, 18 Jan 2015 23:25:13 +0800 Subject: [PATCH 07/10] Removed dataStream and using strea.Transform --- lib/asset.js | 56 +++++++++++++++++++++------------------------------- lib/qiniu.js | 2 +- package.json | 2 +- 3 files changed, 25 insertions(+), 35 deletions(-) diff --git a/lib/asset.js b/lib/asset.js index a0e76d5..f266f5b 100644 --- a/lib/asset.js +++ b/lib/asset.js @@ -2,7 +2,6 @@ var request = require('request'); var Q = require('q'); var util = require('util'); var url = require('url'); -var dataStream = require('dataStream'); var _ = require('underscore'); var utils = require('./utils'); var config = require('./config'); @@ -80,18 +79,15 @@ Asset.prototype.qrcode = function(opts, callback) { var _url = util.format('%s?qrcode/%d/level/%s', this.url(), opts.mode, opts.level); - var recive = new dataStream(); - request(_url).pipe(recive) - .on('error', function(err) { - callback(err); + var recive = request(_url, function(err, resp, body) { + if (err) { deferred.reject(err); - }) - .on('complete', function() { - var data = this.body(); + return callback(err); + } - callback(null, data); - deferred.resolve(data); - }); + deferred.resolve(body); + callback(null, body); + }); var promise = deferred.promise; @@ -277,18 +273,15 @@ Asset.prototype.alias = function(alias, callback) { _url += util.format('%s%s', this.config.separate, alias); - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { + var recive = request(_url, function(err, resp, body) { + if (err) { deferred.reject(err); - callback(err); - }); + return callback(err); + } + + deferred.resolve(body); + callback(null, body); + }); var promise = deferred.promise; @@ -350,18 +343,15 @@ Asset.prototype.md2html = function(opts, callback) { _url += util.format('/css/%s', utils.safeEncode(opts.css)); } - var recive = new dataStream(); - request(_url).pipe(recive) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); - }) - .on('error', function(err) { + var recive = request(_url, function(err, resp, body) { + if (err) { deferred.reject(err); - callback(err); - }); + return callback(err); + } + + deferred.resolve(body); + callback(null, body); + }); return deferred.promise; }; diff --git a/lib/qiniu.js b/lib/qiniu.js index 86fd0b8..c849cf2 100644 --- a/lib/qiniu.js +++ b/lib/qiniu.js @@ -2,7 +2,7 @@ var _ = require('underscore'); var qiniu = exports; -qiniu.version = '6.1.6'; +qiniu.version = '6.1.7'; var _configData = require('./config'); diff --git a/package.json b/package.json index 73259f2..0bfa64d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-qiniu", - "version": "6.1.6", + "version": "6.1.7", "description": "Qiniu Resource Storage SDK for Node.js", "main": "index.js", "directories": { From c27d2fcfbb21ced04b0a170fe8664b320d35c4a7 Mon Sep 17 00:00:00 2001 From: iwillwen Date: Fri, 16 Oct 2015 16:39:42 +0800 Subject: [PATCH 08/10] Update: replace Q with bluebird; Add Asset.fetch() supports --- README.md | 8 + lib/asset.js | 423 ++++++++++++++++++++++++-------------------- lib/batch.js | 80 ++++----- lib/bucket.js | 145 ++++++++------- lib/config.js | 5 +- lib/fop.js | 38 ++-- lib/image.js | 211 +++++++++++----------- package.json | 3 +- test/qiniu_fop.js | 1 - test/qiniu_image.js | 1 - 10 files changed, 477 insertions(+), 438 deletions(-) diff --git a/README.md b/README.md index b8d3d7a..73f9489 100644 --- a/README.md +++ b/README.md @@ -398,6 +398,14 @@ console.dir(getToken); var url = imagesBucket.key('exampleKey').download(); ``` +#### `Asset.fetch()` + +`Asset.fetch()`方法用于从指定地址拉取链接,并保存到七牛云存储中。 + +```js +imagesBucket.keys('test.jpg').fetch('http://exampple.com/test.jpg') +``` + ### `Batch` 资源批量操作 在支持对单个文件资源操作的同时,七牛云存储还支持批量地对多个文件进行查看、删除、复制和移动操作。 diff --git a/lib/asset.js b/lib/asset.js index f266f5b..6a1b6c4 100644 --- a/lib/asset.js +++ b/lib/asset.js @@ -1,5 +1,5 @@ var request = require('request'); -var Q = require('q'); +var Promise = require('bluebird'); var util = require('util'); var url = require('url'); var _ = require('underscore'); @@ -62,34 +62,35 @@ Asset.prototype.entryUrl = function() { * @return {Promise} promise object */ Asset.prototype.qrcode = function(opts, callback) { - var deferred = Q.defer(); - switch (true) { - case _.isFunction(opts): - callback = opts; - opts = { mode: 0, level: 'L' }; - break; - case _.isObject(opts) && _.isUndefined(callback): - callback = noop; - break; - case _.isUndefined(opts): - opts = { mode: 0, level: 'L' }; - callback = noop; - break; - } - - var _url = util.format('%s?qrcode/%d/level/%s', this.url(), opts.mode, opts.level); - - var recive = request(_url, function(err, resp, body) { - if (err) { - deferred.reject(err); - return callback(err); + var self = this + var recive = null + var promise = new Promise(function(resolve, reject) { + switch (true) { + case _.isFunction(opts): + callback = opts; + opts = { mode: 0, level: 'L' }; + break; + case _.isObject(opts) && _.isUndefined(callback): + callback = noop; + break; + case _.isUndefined(opts): + opts = { mode: 0, level: 'L' }; + callback = noop; + break; } - deferred.resolve(body); - callback(null, body); - }); + var _url = util.format('%s?qrcode/%d/level/%s', self.url(), opts.mode, opts.level); - var promise = deferred.promise; + recive = request(_url, function(err, resp, body) { + if (err) { + reject(err); + return callback(err); + } + + resolve(body); + callback(null, body); + }); + }) promise.stream = function() { return recive; @@ -104,38 +105,38 @@ Asset.prototype.qrcode = function(opts, callback) { * @return {Promise} promise object */ Asset.prototype.stat = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var path = util.format('/stat/%s', this.entryUrl()); - var _url = url.format({ - protocol: 'http', - hostname: config.rsUrl, - pathname: path - }); - - var token = this.access_token.token(path, null); - - request({ - url: _url, - method: 'POST', - headers: { - 'Authorization': token, - 'Content-Type': 'application/x-www-form-urlencoded' - } - }, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } - - var result = JSON.parse(body); - - deferred.resolve(result); - callback(null, result); - }); + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; - return deferred.promise; + var path = util.format('/stat/%s', self.entryUrl()); + var _url = url.format({ + protocol: 'http', + hostname: config.rsUrl, + pathname: path + }); + + var token = self.access_token.token(path, null); + + request({ + url: _url, + method: 'POST', + headers: { + 'Authorization': token, + 'Content-Type': 'application/x-www-form-urlencoded' + } + }, function(err, res, body) { + if (err) { + reject(err); + return callback(err); + } + + var result = JSON.parse(body); + + resolve(result); + callback(null, result); + }); + }) }; /** @@ -145,37 +146,37 @@ Asset.prototype.stat = function(callback) { * @return {Promise} promise object */ Asset.prototype.move = function(destAsset, callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var path = util.format('/move/%s/%s', this.entryUrl(), destAsset.entryUrl()); - var _url = url.format({ - protocol: 'http', - hostname: config.rsUrl, - pathname: path - }); - - var token = this.access_token.token(path, null); - - request({ - url: _url, - method: 'POST', - headers: { - 'Authorization': token, - 'Content-Type': 'application/x-www-form-urlencoded' - } - }, function(err, res) { - if (err) { - deferred.reject(err); - return callback(err); - } - - - deferred.resolve(); - callback(null); - }); + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; - return deferred.promise; + var path = util.format('/move/%s/%s', self.entryUrl(), destAsset.entryUrl()); + var _url = url.format({ + protocol: 'http', + hostname: config.rsUrl, + pathname: path + }); + + var token = self.access_token.token(path, null); + + request({ + url: _url, + method: 'POST', + headers: { + 'Authorization': token, + 'Content-Type': 'application/x-www-form-urlencoded' + } + }, function(err, res) { + if (err) { + reject(err); + return callback(err); + } + + + resolve(); + callback(null); + }); + }) }; /** @@ -185,36 +186,36 @@ Asset.prototype.move = function(destAsset, callback) { * @return {Promise} promise object */ Asset.prototype.copy = function(destAsset, callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var path = util.format('/copy/%s/%s', this.entryUrl(), destAsset.entryUrl()); - var _url = url.format({ - protocol: 'http', - hostname: config.rsUrl, - pathname: path - }); - - var token = this.access_token.token(path, null); - - request({ - url: _url, - method: 'POST', - headers: { - 'Authorization': token, - 'Content-Type': 'application/x-www-form-urlencoded' - } - }, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } - - deferred.resolve(); - callback(null); - }); + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; - return deferred.promise; + var path = util.format('/copy/%s/%s', self.entryUrl(), destAsset.entryUrl()); + var _url = url.format({ + protocol: 'http', + hostname: config.rsUrl, + pathname: path + }); + + var token = self.access_token.token(path, null); + + request({ + url: _url, + method: 'POST', + headers: { + 'Authorization': token, + 'Content-Type': 'application/x-www-form-urlencoded' + } + }, function(err, res, body) { + if (err) { + reject(err); + return callback(err); + } + + resolve(); + callback(null); + }); + }) }; /** @@ -223,36 +224,69 @@ Asset.prototype.copy = function(destAsset, callback) { * @return {Promise} promise object */ Asset.prototype.remove = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var path = util.format('/delete/%s', this.entryUrl()); - var _url = url.format({ - protocol: 'http', - hostname: config.rsUrl, - pathname: path - }); - - var token = this.access_token.token(path, null); + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; - request({ - url: _url, - method: 'POST', - headers: { - 'Authorization': token, - 'Content-Type': 'application/x-www-form-urlencoded' - } - }, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } + var path = util.format('/delete/%s', self.entryUrl()); + var _url = url.format({ + protocol: 'http', + hostname: config.rsUrl, + pathname: path + }); + + var token = self.access_token.token(path, null); + + request({ + url: _url, + method: 'POST', + headers: { + 'Authorization': token, + 'Content-Type': 'application/x-www-form-urlencoded' + } + }, function(err, res, body) { + if (err) { + reject(err); + return callback(err); + } + + resolve(); + callback(null); + }); + }) +}; - deferred.resolve(); - callback(null); - }); +Asset.prototype.fetch = function(url, callback) { + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; - return deferred.promise; + var path = util.format('/fetch/%s/to/%s', utils.safeEncode(url), self.entryUrl()); + var _url = url.format({ + protocol: 'http', + hostname: config.vipUrl, + pathname: path + }); + + var token = self.access_token.token(path, null); + + request({ + url: _url, + method: 'POST', + headers: { + 'Authorization': token, + 'Content-Type': 'application/x-www-form-urlencoded' + } + }, function(err, res, body) { + if (err) { + reject(err); + return callback(err); + } + + resolve(); + callback(null); + }); + }) }; Asset.prototype.fop = function(config) { @@ -266,24 +300,25 @@ Asset.prototype.fop = function(config) { * @return {Promise} promise object */ Asset.prototype.alias = function(alias, callback) { - var deferred = Q.defer(); - callback = callback || noop; + var self = this + var recive = null + var promise = new Promise(function(resolve, reject) { + callback = callback || noop; - var _url = this.url(); + var _url = self.url(); - _url += util.format('%s%s', this.config.separate, alias); - - var recive = request(_url, function(err, resp, body) { - if (err) { - deferred.reject(err); - return callback(err); - } + _url += util.format('%s%s', self.config.separate, alias); + + recive = request(_url, function(err, resp, body) { + if (err) { + reject(err); + return callback(err); + } - deferred.resolve(body); - callback(null, body); - }); - - var promise = deferred.promise; + resolve(body); + callback(null, body); + }); + }) /** * return the image stream @@ -315,45 +350,51 @@ Asset.prototype.download = function(filename) { * @return {Promise} promise object */ Asset.prototype.md2html = function(opts, callback) { - var deferred = Q.defer(); - - if (_.isFunction(opts)) { - callback = opts; - opts = { - mode: false, - css: false - }; - } else if (_.isObject(opts)) { - callback = callback || noop; - } else { - callback = callback || noop; - opts = { - mode: false, - css: false - }; - } - - var _url = this.url() + '?md2html'; + var self = this + var recive = null + var promise = new Promise(function(resolve, reject) { + if (_.isFunction(opts)) { + callback = opts; + opts = { + mode: false, + css: false + }; + } else if (_.isObject(opts)) { + callback = callback || noop; + } else { + callback = callback || noop; + opts = { + mode: false, + css: false + }; + } - if (opts.mode) { - _url += util.format('/%s', opts.mode); - } + var _url = self.url() + '?md2html'; - if (opts.css) { - _url += util.format('/css/%s', utils.safeEncode(opts.css)); - } + if (opts.mode) { + _url += util.format('/%s', opts.mode); + } - var recive = request(_url, function(err, resp, body) { - if (err) { - deferred.reject(err); - return callback(err); + if (opts.css) { + _url += util.format('/css/%s', utils.safeEncode(opts.css)); } - deferred.resolve(body); - callback(null, body); - }); + recive = request(_url, function(err, resp, body) { + if (err) { + reject(err); + return callback(err); + } + + resolve(body); + callback(null, body); + }); + }) + + promise.stream = function() { + return recive + } - return deferred.promise; + return promise }; module.exports = Asset; diff --git a/lib/batch.js b/lib/batch.js index 9335faa..b20235d 100644 --- a/lib/batch.js +++ b/lib/batch.js @@ -1,5 +1,5 @@ var request = require('request'); -var Q = require('q'); +var Promise = require('bluebird'); var _ = require('underscore'); var util = require('util'); var url = require('url'); @@ -73,45 +73,45 @@ Batch.prototype.remove = function(asset) { * @return {Promise} promise object */ Batch.prototype.exec = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var _url = url.format({ - protocol: 'http', - hostname: this.config.rsUrl, - pathname: '/batch' - }); - var body = this.op.substr(1); - var token = this.access_token.token('/batch', body); - - request({ - url: _url, - method: 'POST', - body: body, - headers: { - 'Authorization': token, - 'Content-Type': 'application/x-www-form-urlencoded' - }, - }, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } - - if (body.length > 0) { - var rows = JSON.parse(body); - - deferred.resolve(rows); - callback(null, rows); - } else { - err = new Error(http.STATUS_CODES[503]); - - deferred.reject(err); - callback(err); - } - }); - - return deferred.promise; + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; + + var _url = url.format({ + protocol: 'http', + hostname: self.config.rsUrl, + pathname: '/batch' + }); + var body = self.op.substr(1); + var token = self.access_token.token('/batch', body); + + request({ + url: _url, + method: 'POST', + body: body, + headers: { + 'Authorization': token, + 'Content-Type': 'application/x-www-form-urlencoded' + }, + }, function(err, res, body) { + if (err) { + reject(err); + return callback(err); + } + + if (body.length > 0) { + var rows = JSON.parse(body); + + resolve(rows); + callback(null, rows); + } else { + err = new Error(http.STATUS_CODES[503]); + + reject(err); + callback(err); + } + }); + }) }; module.exports = Batch; diff --git a/lib/bucket.js b/lib/bucket.js index 78b0bf4..5a20475 100644 --- a/lib/bucket.js +++ b/lib/bucket.js @@ -2,7 +2,7 @@ var request = require('request'); var _ = require('underscore'); var fs = require('fs'); var path = require('path'); -var Q = require('q'); +var Promise = require('bluebird'); var util = require('util'); var url = require('url'); var path = require('path'); @@ -53,58 +53,58 @@ function Bucket(bucketName, config) { * @return {Promise} Promise object */ Bucket.prototype.putFile = function(key, pathname, options, callback) { + var self = this + var args = [].slice.apply(arguments) // token - var deferred = Q.defer(); - - switch (arguments.length) { - case 3: - if (_.isFunction(options)) { - callback = options; + return new Promise(function(resolve, reject) { + switch (args.length) { + case 3: + if (_.isFunction(options)) { + callback = options; + options = {}; + } + break; + case 2: options = {}; - } - break; - case 2: - options = {}; - callback = noop; - break; - } + callback = noop; + break; + } - var config = _.extend(_.clone(this.config), options); + var config = _.extend(_.clone(self.config), options); - var putToken = (new token.PutPolicy(config)).token(); + var putToken = (new token.PutPolicy(config)).token(); - // safe pathname - pathname = path.resolve(process.cwd(), pathname); + // safe pathname + pathname = path.resolve(process.cwd(), pathname); - // upload API - var uploadUrl = url.format({ - protocol: 'http', - hostname: globalConfig.uploadUrl - }); - - // uploading - var req = request.post(uploadUrl, function(err, res, body) { - var result = JSON.parse(body); + // upload API + var uploadUrl = url.format({ + protocol: 'http', + hostname: globalConfig.uploadUrl + }); - if (err) { - deferred.reject(err); - return callback(err, result); - } + // uploading + var req = request.post(uploadUrl, function(err, res, body) { + var result = JSON.parse(body); - deferred.resolve(result); - callback(null, result); - }); + if (err) { + reject(err); + return callback(err, result); + } - // form data - var form = req.form(); + resolve(result); + callback(null, result); + }); - form.append('token', putToken); - form.append('key', key); - form.append('file', fs.createReadStream(pathname), { - filename: path.basename(pathname) - }); + // form data + var form = req.form(); - return deferred.promise; + form.append('token', putToken); + form.append('key', key); + form.append('file', fs.createReadStream(pathname), { + filename: path.basename(pathname) + }); + }) }; /** @@ -134,29 +134,30 @@ Bucket.prototype.createPutStream = function(key, options) { hostname: globalConfig.uploadUrl }); - // uploading - var req = request.post(uploadUrl, function(err, res, body) { - var result = JSON.parse(body); - - if (err) { - return _stream.emit('error', err); - } - - _stream.emit('end', result); - }); - - // form data - var form = req.form(); - - form.append('token', putToken); - form.append('key', key); _stream.on('pipe', function(src) { if (src.path) { var filename = path.basename(src.path); } else { var filename = key; } - form.append('file', _stream, { + + // uploading + var req = request.post(uploadUrl, function(err, res, body) { + var result = JSON.parse(body); + + if (err) { + return _stream.emit('error', err); + } + + _stream.emit('end', result); + }); + + // form data + var form = req.form(); + + form.append('token', putToken); + form.append('key', key); + form.append('file', src, { filename: filename }); }); @@ -173,23 +174,19 @@ Bucket.prototype.createPutStream = function(key, options) { Bucket.prototype.getFile = function(key, callback) { // token var getToken = this.key(key).token(); - var deferred = Q.defer(); - callback = callback || noop; + return new Promise(function(resolve, reject) { + callback = callback || noop; - var res = request(getToken.url); - var recive = new stream.Transform(); - recive._transform = function(chunk, encoding, cb) { - cb(); - }; - recive._flush = function(cb) { - callback(); - cb(); - }; - - res.pipe(recive) - .on('error', deferred.reject.bind(deferred)); + request(getToken.url, function(err, res, body) { + if (err) { + callback(err) + return reject(err) + } - return deferred.promise; + callback(null, body) + resolve(body) + }); + }) }; /** diff --git a/lib/config.js b/lib/config.js index a0b3393..ebd92de 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,5 +1,6 @@ module.exports = { - uploadUrl : 'up.qiniu.com', + uploadUrl : 'upload.qiniu.com', rsUrl : 'rs.qbox.me', - rsfUrl : 'rsf.qbox.me' + rsfUrl : 'rsf.qbox.me', + vipUrl : 'iovip.qbox.me' }; \ No newline at end of file diff --git a/lib/fop.js b/lib/fop.js index 2c36f7c..4ea5908 100644 --- a/lib/fop.js +++ b/lib/fop.js @@ -2,8 +2,7 @@ var request = require('request'); var _ = require('underscore'); var fs = require('fs'); var path = require('path'); -var Q = require('q'); -var dataStream = require('dataStream'); +var Promise = require('bluebird'); var util = require('util'); var url = require('url'); var Asset = require('./asset'); @@ -223,24 +222,20 @@ Fop.prototype.token = function() { * @return {Promise} promise object */ Fop.prototype.exec = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var recive = new dataStream(); - request(this.url()) - .pipe(recive) - .on('error', function(err) { - deferred.reject(err); - callback(err); - }) - .on('complete', function() { - var data = this.body(); - - deferred.resolve(data); - callback(null, data); + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; + + request(self.url(), function(err, resp, body) { + if (err) { + reject(err); + return callback(err); + } + + resolve(body); + callback(null, body); }); - - return deferred.promise; + }) }; /** @@ -248,10 +243,7 @@ Fop.prototype.exec = function(callback) { * @return {Stream} stream */ Fop.prototype.stream = function() { - var recive = new dataStream(); - request(this.url()).pipe(recive); - - return recive; + return request(this.url()); }; module.exports = Fop; diff --git a/lib/image.js b/lib/image.js index b312de2..efe8024 100644 --- a/lib/image.js +++ b/lib/image.js @@ -2,8 +2,7 @@ var request = require('request'); var _ = require('underscore'); var fs = require('fs'); var path = require('path'); -var Q = require('q'); -var dataStream = require('dataStream'); +var Promise = require('bluebird'); var stream = require('stream'); var util = require('util'); var url = require('url'); @@ -34,28 +33,28 @@ util.inherits(Image, Asset); * @return {Promise} promise object */ Image.prototype.imageInfo = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; - var getToken = this.token({ - fop: 'imageInfo' - }); - - var _url = getToken.url + '&token=' + getToken.token; + var getToken = self.token({ + fop: 'imageInfo' + }); - request(_url, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } + var _url = getToken.url + '&token=' + getToken.token; - var info = JSON.parse(body); + request(_url, function(err, res, body) { + if (err) { + reject(err); + return callback(err); + } - deferred.resolve(info); - callback(null, info); - }); + var info = JSON.parse(body); - return deferred.promise; + resolve(info); + callback(null, info); + }); + }) }; /** @@ -64,28 +63,28 @@ Image.prototype.imageInfo = function(callback) { * @return {Promise} promise object */ Image.prototype.exif = function(callback) { - var deferred = Q.defer(); - callback = callback || noop; + var self = this + return new Promise(function(resolve, reject) { + callback = callback || noop; - var getToken = this.token({ - fop: 'exif' - }); + var getToken = self.token({ + fop: 'exif' + }); - var _url = getToken.url + '&token=' + getToken.token; + var _url = getToken.url + '&token=' + getToken.token; - request(_url, function(err, res, body) { - if (err) { - deferred.reject(err); - return callback(err); - } + request(_url, function(err, res, body) { + if (err) { + reject(err); + return callback(err); + } - var info = JSON.parse(body); + var info = JSON.parse(body); - deferred.resolve(info); - callback(null, info); - }); - - return deferred.promise; + resolve(info); + callback(null, info); + }); + }) }; var imageViewTranslations = { @@ -101,41 +100,42 @@ var imageViewTranslations = { * @return {Promise} promise object */ Image.prototype.imageView = function(opts, callback) { - var deferred = Q.defer(); - callback = callback || noop; + var self = this + var recive = null + var promise = new Promise(function(resolve, reject) { + callback = callback || noop; - var mode = opts.mode; - delete opts.mode; + var mode = opts.mode; + delete opts.mode; - var params = {}; + var params = {}; - _.each(opts, function(value, key) { - if (imageViewTranslations.hasOwnProperty(key)) { - key = imageViewTranslations[key]; - } + _.each(opts, function(value, key) { + if (imageViewTranslations.hasOwnProperty(key)) { + key = imageViewTranslations[key]; + } - params[key] = value; - }); + params[key] = value; + }); - var fop = util.format('imageView/%d%s', mode, genOptUrl(params)); + var fop = util.format('imageView/%d%s', mode, genOptUrl(params)); - var getToken = this.token({ - fop: fop - }); + var getToken = self.token({ + fop: fop + }); - var _url = getToken.url + '&token=' + getToken.token; + var _url = getToken.url + '&token=' + getToken.token; - var recive = request(_url, function(err, resp, body) { - if (err) { - deferred.reject(err); - return callback(err); - } + recive = request(_url, function(err, resp, body) { + if (err) { + reject(err); + return callback(err); + } - deferred.resolve(body); - callback(null, body); - }); - - var promise = deferred.promise; + resolve(body); + callback(null, body); + }); + }) /** * return the image stream @@ -155,32 +155,33 @@ Image.prototype.imageView = function(opts, callback) { * @return {Promise} promise object */ Image.prototype.imageMogr = function(opts, callback) { - var deferred = Q.defer(); - callback = callback || noop; - - var params = {}; + var self = this + var recive = null + var promise = new Promise(function(resolve, reject) { + callback = callback || noop; - _.extend(params, opts); - - var fop = util.format('imageMogr/v2/auto-orient%s', genOptUrl(params)); + var params = {}; - var getToken = this.token({ - fop: fop - }); + _.extend(params, opts); + + var fop = util.format('imageMogr/v2/auto-orient%s', genOptUrl(params)); - var _url = getToken.url + '&token=' + getToken.token; + var getToken = self.token({ + fop: fop + }); - var recive = request(_url, function(err, resp, body) { - if (err) { - deferred.reject(err); - return callback(err); - } + var _url = getToken.url + '&token=' + getToken.token; - deferred.resolve(body); - callback(null, body); - }); + recive = request(_url, function(err, resp, body) { + if (err) { + reject(err); + return callback(err); + } - var promise = deferred.promise; + resolve(body); + callback(null, body); + }); + }) /** * return the image stream @@ -200,36 +201,37 @@ Image.prototype.imageMogr = function(opts, callback) { * @return {Promise} promise object */ Image.prototype.watermark = function(opts, callback) { - var deferred = Q.defer(); - callback = callback || noop; + var self = this + var recive = null + var promise = new Promise(function(resolve, reject) { + callback = callback || noop; - var params = {}; - var mode = opts.mode; - delete opts.mode; + var params = {}; + var mode = opts.mode; + delete opts.mode; - _.extend(params, opts); + _.extend(params, opts); - params.image = utils.safeEncode(params.image); + params.image = utils.safeEncode(params.image); - var fop = util.format('watermark/%d%s', mode, genOptUrl(params)); + var fop = util.format('watermark/%d%s', mode, genOptUrl(params)); - var getToken = this.token({ - fop: fop - }); - - var _url = getToken.url + '&token=' + getToken.token; + var getToken = self.token({ + fop: fop + }); - var recive = request(_url, function(err, resp, body) { - if (err) { - deferred.reject(err); - return callback(err); - } + var _url = getToken.url + '&token=' + getToken.token; - deferred.resolve(body); - callback(null, body); - }); + recive = request(_url, function(err, resp, body) { + if (err) { + reject(err); + return callback(err); + } - var promise = deferred.promise; + resolve(body); + callback(null, body); + }); + }) /** * return the image stream @@ -238,7 +240,6 @@ Image.prototype.watermark = function(opts, callback) { promise.stream = function() { return recive; }; - return promise; }; diff --git a/package.json b/package.json index 0bfa64d..cb61be3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-qiniu", - "version": "6.1.7", + "version": "6.1.9", "description": "Qiniu Resource Storage SDK for Node.js", "main": "index.js", "directories": { @@ -36,6 +36,7 @@ "url": "https://www.npmjs.org/package/node-qiniu/issues" }, "dependencies": { + "bluebird": "^2.10.2", "bufferhelper": "^0.2.0", "q": "~0.9.6", "request": "~2.27.0", diff --git a/test/qiniu_fop.js b/test/qiniu_fop.js index 07d36dc..f355496 100644 --- a/test/qiniu_fop.js +++ b/test/qiniu_fop.js @@ -1,6 +1,5 @@ var qiniu = require('./'); var fs = require('fs'); -var dataStream = require('dataStream'); var assert = require('assert'); var asset = qiniu.testBucket.key('gogopher.jpg'); diff --git a/test/qiniu_image.js b/test/qiniu_image.js index 6c20744..71ac2c6 100644 --- a/test/qiniu_image.js +++ b/test/qiniu_image.js @@ -1,6 +1,5 @@ var qiniu = require('./'); var fs = require('fs'); -var dataStream = require('dataStream'); var assert = require('assert'); var image = qiniu.testBucket.image('gogopher.jpg'); From eb5596829e3db4e473db1c8ad34a555cd12e0ce0 Mon Sep 17 00:00:00 2001 From: iwillwen Date: Fri, 16 Oct 2015 16:40:15 +0800 Subject: [PATCH 09/10] Update: replace Q with bluebird; Add Asset.fetch() supports --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cb61be3..4153177 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-qiniu", - "version": "6.1.9", + "version": "6.2.0", "description": "Qiniu Resource Storage SDK for Node.js", "main": "index.js", "directories": { From be52ca94f884bfaab477f65b751c975ccf4ad4ca Mon Sep 17 00:00:00 2001 From: iwillwen Date: Fri, 16 Oct 2015 16:44:41 +0800 Subject: [PATCH 10/10] Update: CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a9d69e2..bb88a5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ language: node_js node_js: - "0.10" - - "0.8" + - "4"