ssh2-sftp-client 1.0.4 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@ let sftp = new Client();
11
11
  sftp.connect({
12
12
  host: '127.0.0.1',
13
13
  port: '8080',
14
- username: 'username'
14
+ username: 'username',
15
15
  password: '******'
16
16
  }).then(() => {
17
17
  return sftp.list('/pathname');
@@ -52,19 +52,19 @@ group: // group ID
52
52
  ```
53
53
 
54
54
  #### Get
55
- get a new readable stream for path.
55
+ get a new readable stream for path. The encoding is passed to Node Stream (https://nodejs.org/api/stream.html) and it controls how the content is encoded. For example, when downloading binary data, 'null' should be passed (check node stream documentation). Defaults to 'utf8'.
56
56
 
57
57
  ```
58
- sftp.get(romoteFilePath, [useCompression]);
58
+ sftp.get(remoteFilePath, [useCompression], [encoding]);
59
59
  ```
60
60
 
61
61
  #### Put
62
62
  upload a file. it can be `localPath` or `Buffer` or `Stream`.
63
63
 
64
64
  ```
65
- sftp.put(localFilePath, remoteFilePath, [useCompression]);
66
- sftp.put(Buffer, remoteFilePath, [useCompression]);
67
- sftp.put(Stream, remoteFilePath, [useCompression]);
65
+ sftp.put(localFilePath, remoteFilePath, [useCompression], [encoding]);
66
+ sftp.put(Buffer, remoteFilePath, [useCompression], [encoding]);
67
+ sftp.put(Stream, remoteFilePath, [useCompression], [encoding]);
68
68
  ```
69
69
 
70
70
  #### Mkdir
@@ -91,10 +91,17 @@ sftp.delete(remoteFilePath);
91
91
  ```
92
92
 
93
93
  #### Rename
94
- rename/remove remoteSourcePath to remoteDestPath.
94
+ rename remoteSourcePath to remoteDestPath (removes remoteSourcePath).
95
95
 
96
96
  ```
97
- sftp.remove(remoteSourcePath, remoteDestPath);
97
+ sftp.rename(remoteSourcePath, remoteDestPath);
98
+ ```
99
+
100
+ #### Chmod
101
+ modify rights to remoteDestPath file
102
+
103
+ ```
104
+ sftp.chmod(remoteDestPath, mode);
98
105
  ```
99
106
 
100
107
  #### Connect
@@ -103,7 +110,11 @@ connection config you will see [here](https://github.com/mscdex/ssh2#user-conten
103
110
  ### FAQ
104
111
 
105
112
  ### Log
106
- * 2016.05.19:
113
+ #### V1.1.0
114
+ - fix: add encoding control support for binary stream
115
+
116
+ #### V1.0.5:
117
+
107
118
  - fix: multi image upload
108
119
  - change: remove `this.client.sftp` to `connect` function
109
120
 
package/example/demo.js CHANGED
@@ -1,58 +1,80 @@
1
1
  'use strict';
2
2
 
3
- let fs = require('fs');
4
- let Client = require('../src/index.js');
5
-
6
- let config = require('../tmp/ftp_config');
7
- let sftp = new Client();
8
-
9
- const BASIC_URL = '/sftp/edm/xucj/';
10
-
11
- sftp.connect(config)
12
- // add test delete
13
- // .then(() => {
14
- // return sftp.put('/Library/WebServer/Documents/nodejs/ssh2-sftp-client/test.html', BASIC_URL + 'bb/a1.html');
15
- // })
16
- // .then(() => {
17
- // return sftp.mkdir(BASIC_URL + 'bb/aa', true);
18
- // })
19
-
20
- // .then((data) => sftp.list(BASIC_URL))
21
- // .then(() => {
22
- // let str = '<body>string html</body>';
23
- // let filePath = '/Library/WebServer/Documents/nodejs/ssh2-sftp-client/test.html';
24
- // let buffer = new Buffer('this is the bufffffer test');
25
- // let stream = fs.createReadStream(filePath);
26
-
27
- // // test ok.
28
- // // return sftp.put(filePath, BASIC_URL + 'hello1.html');
29
- // // test ok.
30
- // // sftp.put(buffer, BASIC_URL + 'hello3.html');
31
- // // test ok.
32
- // // sftp.put(stream, BASIC_URL + 'h5.html');
33
- // })
34
-
35
- // .then(() => {
36
- // return sftp.get(BASIC_URL + 'hello1.html');
37
- // })
38
-
39
- // .then(() => {
40
- // return sftp.mkdir(BASIC_URL + 'qq1/tt/a1.html', true);
41
- // })
42
-
43
- // .then(() => {
44
- // return sftp.delete(BASIC_URL + 'hello1.html');
45
- // })
46
-
47
- // .then(() => {
48
- // return sftp.rename(BASIC_URL + 'h5.html', BASIC_URL + 'bb/ooo.html');
49
- // })
50
-
51
- .then(() => {
52
- return sftp.rmdir(BASIC_URL + 'mocha-rmdir', true);
53
- })
3
+ const fs = require('fs');
4
+ const Client = require('../src/index.js');
5
+ const sftp = new Client();
6
+ const BASIC_URL = '/sftp-test/';
7
+
8
+ const config = {
9
+ host: '127.0.0.1',
10
+ port: '8080',
11
+ username: 'username',
12
+ password: '******'
13
+ };
14
+
15
+ // get connect
16
+ const connect = () => {
17
+ sftp.connect(config);
18
+ };
54
19
 
55
- .then((data) => {
56
- console.log(data, 'end data');
20
+ // get list
21
+ const list = () => {
22
+ sftp.connect(config).then(() => {
23
+ return sftp.list(BASIC_URL);
24
+ }).then((data) => {
25
+ let body = data.on('data', (chunk) => {
26
+ body += chunk;
27
+ });
28
+
29
+ data.on('end', () => {
30
+ console.log(body)
31
+ });
57
32
  })
58
- .catch((err) => console.log(err, 'catch error'));
33
+ };
34
+
35
+ // get file
36
+ const get = () => {
37
+ sftp.connect(config).then(() => {
38
+ return sftp.get(BASIC_URL + 'a.js');
39
+ });
40
+ };
41
+
42
+ // put file
43
+ const put1 = () => {
44
+ sftp.connect(config).then(() => {
45
+ return sftp.put(BASIC_URL + 'localpath.js', BASIC_URL + 'remotepath.js');
46
+ });
47
+ };
48
+ const put2 = () => {
49
+ sftp.connect(config).then(() => {
50
+ return sftp.put(new Buffer('hello'), BASIC_URL + 'file.js', true, 'utf-8');
51
+ });
52
+ };
53
+
54
+ // mkdir
55
+ const mkdir = () => {
56
+ sftp.connect(config).then(() => {
57
+ return sftp.mkdir(BASIC_URL + 'change/log', true);
58
+ });
59
+ };
60
+
61
+ // rmdir
62
+ const rmdir = () => {
63
+ sftp.connect(config).then(() => {
64
+ return sftp.rmdir(BASIC_URL + 'change/log', true);
65
+ });
66
+ };
67
+
68
+ // delete
69
+ const deleteFile = () => {
70
+ sftp.connect(config).then(() => {
71
+ return sftp.delete(BASIC_URL + 'file.js');
72
+ });
73
+ }
74
+
75
+ // rename
76
+ const rename = () => {
77
+ sftp.connect(config).then(() => {
78
+ return sftp.rename(BASIC_URL + 'source.js', BASIC_URL + 'remote.js');
79
+ });
80
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ssh2-sftp-client",
3
- "version": "1.0.4",
3
+ "version": "2.0.1",
4
4
  "description": "ssh2 sftp client for node",
5
5
  "main": "src/index.js",
6
6
  "repository": {
@@ -18,7 +18,7 @@
18
18
  "email": "jyu213@gmail.com",
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
- "ssh2": "^0.4.13"
21
+ "ssh2": "^0.5.5"
22
22
  },
23
23
  "devDependencies": {
24
24
  "chai": "^3.5.0",
package/src/index.js CHANGED
@@ -47,7 +47,7 @@ SftpClient.prototype.list = function(path) {
47
47
  resolve(list);
48
48
  });
49
49
  } else {
50
- reject('sftp connect error');
50
+ reject(Error('sftp connect error'));
51
51
  }
52
52
  });
53
53
  };
@@ -57,22 +57,30 @@ SftpClient.prototype.list = function(path) {
57
57
  *
58
58
  * @param {String} path, path
59
59
  * @param {Object} useCompression, config options
60
+ * @param {String} encoding. Encoding for the ReadStream, can be any value supported by node streams. Use 'null' for binary (https://nodejs.org/api/stream.html#stream_readable_setencoding_encoding)
60
61
  * @return {Promise} stream, readable stream
61
62
  */
62
- SftpClient.prototype.get = function(path, useCompression) {
63
- useCompression = Object.assign({}, {encoding: 'utf8'}, useCompression);
63
+ SftpClient.prototype.get = function(path, useCompression, encoding) {
64
+ let options = this.getOptions(useCompression, encoding)
64
65
 
65
66
  return new Promise((resolve, reject) => {
66
67
  let sftp = this.sftp;
67
68
 
68
69
  if (sftp) {
69
70
  try {
70
- resolve(sftp.createReadStream(path, useCompression));
71
+ let stream = sftp.createReadStream(path, options);
72
+
73
+ stream.on('error', (err) => {
74
+ reject(err);
75
+ });
76
+ stream.on('readable', () => {
77
+ resolve(stream);
78
+ });
71
79
  } catch(err) {
72
80
  reject(err);
73
81
  }
74
82
  } else {
75
- reject('sftp connect error');
83
+ reject(Error('sftp connect error'));
76
84
  }
77
85
  });
78
86
  };
@@ -83,17 +91,18 @@ SftpClient.prototype.get = function(path, useCompression) {
83
91
  * @param {String|Buffer|stream} input
84
92
  * @param {String} remotePath,
85
93
  * @param {Object} useCompression [description]
94
+ * @param {String} encoding. Encoding for the WriteStream, can be any value supported by node streams.
86
95
  * @return {[type]} [description]
87
96
  */
88
- SftpClient.prototype.put = function(input, remotePath, useCompression) {
89
- useCompression = Object.assign({}, {encoding: 'utf8'}, useCompression);
97
+ SftpClient.prototype.put = function(input, remotePath, useCompression, encoding) {
98
+ let options = this.getOptions(useCompression, encoding)
90
99
 
91
100
  return new Promise((resolve, reject) => {
92
101
  let sftp = this.sftp;
93
102
 
94
103
  if (sftp) {
95
104
  if (typeof input === 'string') {
96
- sftp.fastPut(input, remotePath, useCompression, (err) => {
105
+ sftp.fastPut(input, remotePath, options, (err) => {
97
106
  if (err) {
98
107
  reject(err);
99
108
  return false;
@@ -102,12 +111,11 @@ SftpClient.prototype.put = function(input, remotePath, useCompression) {
102
111
  });
103
112
  return false;
104
113
  }
105
- let stream = sftp.createWriteStream(remotePath, useCompression);
114
+ let stream = sftp.createWriteStream(remotePath, options);
106
115
  let data;
107
116
 
108
- stream.on('close', () => {
109
- resolve();
110
- });
117
+ stream.on('error', reject);
118
+ stream.on('close', resolve);
111
119
 
112
120
  if (input instanceof Buffer) {
113
121
  data = stream.end(input);
@@ -115,7 +123,7 @@ SftpClient.prototype.put = function(input, remotePath, useCompression) {
115
123
  }
116
124
  data = input.pipe(stream);
117
125
  } else {
118
- reject('sftp connect error');
126
+ reject(Error('sftp connect error'));
119
127
  }
120
128
  });
121
129
  };
@@ -159,7 +167,7 @@ SftpClient.prototype.mkdir = function(path, recursive) {
159
167
  };
160
168
  return mkdir();
161
169
  } else {
162
- reject('sftp connect error');
170
+ reject(Error('sftp connect error'));
163
171
  }
164
172
  });
165
173
  };
@@ -230,7 +238,7 @@ SftpClient.prototype.rmdir = function(path, recursive) {
230
238
  return rmdir(path).then(() => {resolve()})
231
239
  .catch((err) => {reject(err)});
232
240
  } else {
233
- reject('sftp connect error');
241
+ reject(Error('sftp connect error'));
234
242
  }
235
243
  });
236
244
  };
@@ -248,7 +256,7 @@ SftpClient.prototype.delete = function(path) {
248
256
  resolve();
249
257
  });
250
258
  } else {
251
- reject('sftp connect error');
259
+ reject(Error('sftp connect error'));
252
260
  }
253
261
  });
254
262
  };
@@ -266,17 +274,35 @@ SftpClient.prototype.rename = function(srcPath, remotePath) {
266
274
  resolve();
267
275
  });
268
276
  } else {
269
- reject('sftp connect error');
277
+ reject(Error('sftp connect error'));
278
+ }
279
+ });
280
+ }
281
+
282
+ SftpClient.prototype.chmod = function(remotePath, mode) {
283
+ return new Promise((resolve, reject) => {
284
+ let sftp = this.sftp;
285
+
286
+ if (sftp) {
287
+ sftp.chmod(remotePath, mode, (err) => {
288
+ if (err) {
289
+ reject(err);
290
+ return false;
291
+ }
292
+ resolve();
293
+ });
294
+ } else {
295
+ reject(Error('sftp connect error'));
270
296
  }
271
297
  });
272
298
  }
273
299
 
274
- SftpClient.prototype.connect = function(config) {
300
+ SftpClient.prototype.connect = function(config, connectMethod) {
301
+ connectMethod = connectMethod || 'on'
275
302
  var c = this.client;
276
303
 
277
304
  return new Promise((resolve, reject) => {
278
- this.client.on('ready', () => {
279
-
305
+ this.client[connectMethod]('ready', () => {
280
306
  this.client.sftp((err, sftp) => {
281
307
  if (err) {
282
308
  reject(err);
@@ -297,4 +323,12 @@ SftpClient.prototype.end = function() {
297
323
  });
298
324
  };
299
325
 
326
+ SftpClient.prototype.getOptions = function(useCompression, encoding){
327
+ if(encoding === undefined){
328
+ encoding = 'utf8';
329
+ }
330
+ let options = Object.assign({}, {encoding: encoding}, useCompression);
331
+ return options;
332
+ };
333
+
300
334
  module.exports = SftpClient;
package/test/index.js CHANGED
@@ -1,14 +1,18 @@
1
- 'use strict';
2
- let stream = require('stream');
3
-
4
- let chai = require('chai');
5
- let expect = chai.expect;
6
- let chaiSubset = require('chai-subset');
7
-
8
- let config = require('../tmp/ftp_config.js');
9
- let Client = require('../src/index.js');
10
- let sftp = new Client();
11
- const BASIC_URL = '/sftp/edm/xucj/';
1
+ const stream = require('stream');
2
+ const chai = require('chai');
3
+ const path = require('path');
4
+ const expect = chai.expect;
5
+ const chaiSubset = require('chai-subset');
6
+ const Client = require('../src/index.js');
7
+ const sftp = new Client();
8
+
9
+ // use your test ssh server config
10
+ const config = {
11
+ host: '172.29.84.8',
12
+ username: 'jyu213',
13
+ password: '**'
14
+ };
15
+ const BASIC_URL = path.resolve(__dirname, '../testServer/') + '/';
12
16
 
13
17
  after(() => {
14
18
  sftp.end();
@@ -18,7 +22,7 @@ describe('list', () => {
18
22
  chai.use(chaiSubset);
19
23
 
20
24
  before(() => {
21
- return sftp.connect(config).then(() => {
25
+ return sftp.connect(config, 'once').then(() => {
22
26
  return sftp.mkdir(BASIC_URL + 'mocha-list/dir1', true);
23
27
  }).then(() => {
24
28
  return sftp.mkdir(BASIC_URL + 'mocha-list/dir2/sub1', true);
@@ -29,7 +33,7 @@ describe('list', () => {
29
33
  });
30
34
  });
31
35
  after(() => {
32
- return sftp.connect(config).then(() => {
36
+ return sftp.connect(config, 'once').then(() => {
33
37
  return sftp.rmdir(BASIC_URL + 'mocha-list', true)
34
38
  .then(() => {
35
39
  return sftp.end();
@@ -53,12 +57,12 @@ describe('list', () => {
53
57
 
54
58
  describe('get', () => {
55
59
  before(() => {
56
- return sftp.connect(config).then(() => {
60
+ return sftp.connect(config, 'once').then(() => {
57
61
  return sftp.put(new Buffer('hello'), BASIC_URL + 'mocha-file.md', true);
58
62
  });
59
63
  });
60
64
  after(() => {
61
- return sftp.connect(config).then(() => {
65
+ return sftp.connect(config, 'once').then(() => {
62
66
  sftp.delete(BASIC_URL + 'mocha-file.md');
63
67
  }).then(() => {
64
68
  return sftp.end();
@@ -79,11 +83,16 @@ describe('get', () => {
79
83
  });
80
84
  });
81
85
  });
86
+ it('get file faild', () => {
87
+ return sftp.get(BASIC_URL + 'mocha-file1.md').catch((err) => {
88
+ expect(err.message).to.equal('No such file');
89
+ });
90
+ });
82
91
  });
83
92
 
84
93
  describe('put', () => {
85
94
  before(() => {
86
- return sftp.connect(config);
95
+ return sftp.connect(config, 'once');
87
96
  });
88
97
  after(() => {
89
98
  return sftp.delete(BASIC_URL + 'mocha-put-string.md').then(() => {
@@ -136,7 +145,7 @@ describe('mkdir', () => {
136
145
  chai.use(chaiSubset);
137
146
 
138
147
  before(() => {
139
- return sftp.connect(config);
148
+ return sftp.connect(config, 'once');
140
149
  });
141
150
  after(() => {
142
151
  return sftp.rmdir(BASIC_URL + 'mocha', true).then(() => {
@@ -167,10 +176,10 @@ describe('rmdir', () => {
167
176
  chai.use(chaiSubset);
168
177
 
169
178
  // beforeEach(() => {
170
- // return sftp.connect(config);
179
+ // return sftp.connect(config, 'once');
171
180
  // });
172
181
  before(() => {
173
- return sftp.connect(config).then(() => {
182
+ return sftp.connect(config, 'once').then(() => {
174
183
  return sftp.mkdir(BASIC_URL + 'mocha-rmdir/dir1', true);
175
184
  }).then(() => {
176
185
  return sftp.mkdir(BASIC_URL + 'mocha-rmdir/dir2', true);
@@ -199,7 +208,7 @@ describe('rmdir', () => {
199
208
  });
200
209
 
201
210
  it('remove directory recursive', () => {
202
- return sftp.connect(config).then(() => {
211
+ return sftp.connect(config, 'once').then(() => {
203
212
  sftp.rmdir(BASIC_URL + 'mocha-rmdir', true).then(() => {
204
213
  return sftp.list(BASIC_URL);
205
214
  }).then((list) => {
@@ -213,7 +222,7 @@ describe('delete', () => {
213
222
  chai.use(chaiSubset);
214
223
 
215
224
  before(() => {
216
- return sftp.connect(config).then(() => {
225
+ return sftp.connect(config, 'once').then(() => {
217
226
  sftp.put(new Buffer('hello'), BASIC_URL + 'mocha-delete.md', true);
218
227
  });
219
228
  });
@@ -238,7 +247,7 @@ describe('rename', () => {
238
247
  chai.use(chaiSubset);
239
248
 
240
249
  before(() => {
241
- return sftp.connect(config).then(() => {
250
+ return sftp.connect(config, 'once').then(() => {
242
251
  return sftp.put(new Buffer('hello'), BASIC_URL + 'mocha-rename.md', true);
243
252
  });
244
253
  });
@@ -260,3 +269,53 @@ describe('rename', () => {
260
269
  });
261
270
  });
262
271
  });
272
+
273
+ describe('getOptions', () => {
274
+
275
+ it('encoding should be utf8 if undefined', () => {
276
+ return expect(sftp.getOptions()).to.have.property('encoding', 'utf8')
277
+ });
278
+
279
+ it('encoding should be utf8 if undefined 1', () => {
280
+ return expect(sftp.getOptions(false)).to.have.property('encoding', 'utf8')
281
+ });
282
+
283
+ it('encoding should be utf8 if undefined 2', () => {
284
+ return expect(sftp.getOptions(false, undefined)).to.have.property('encoding', 'utf8')
285
+ });
286
+
287
+ it('encoding should be null if null', () => {
288
+ return expect(sftp.getOptions(false, null)).to.have.property('encoding', null)
289
+ });
290
+
291
+ it('encoding should be hex', () => {
292
+ return expect(sftp.getOptions(false, 'hex')).to.have.property('encoding', 'hex')
293
+ });
294
+ });
295
+
296
+ describe('chmod', () => {
297
+ chai.use(chaiSubset);
298
+
299
+ before(() => {
300
+ return sftp.connect(config, 'once').then(() => {
301
+ return sftp.put(new Buffer('hello'), BASIC_URL + 'mocha-chmod.txt', true);
302
+ });
303
+ });
304
+ after(() => {
305
+ return sftp.delete(BASIC_URL + 'mocha-chmod.txt').then(() => {
306
+ sftp.end();
307
+ });
308
+ });
309
+
310
+ it('return should be a promise', () => {
311
+ return expect(sftp.chmod(BASIC_URL + 'mocha-chmod.txt', 0777)).to.be.a('promise');
312
+ });
313
+
314
+ it('chmod file', () => {
315
+ return sftp.chmod(BASIC_URL + 'mocha-chmod.txt', 0777).then(() => {
316
+ return sftp.list(BASIC_URL);
317
+ }).then((list) => {
318
+ return expect(list).to.containSubset([{'name': 'mocha-chmod.txt', 'rights': { 'user': 'rwx', 'group': 'rwx', 'other': 'rwx' }}]);
319
+ });
320
+ });
321
+ });
@@ -0,0 +1 @@
1
+ hello
package/test/test.js DELETED
@@ -1,9 +0,0 @@
1
- 'use strict';
2
-
3
- let expect = require('chai').expect;
4
-
5
- describe('list', function() {
6
- it('should return the list name of each', function() {
7
- expect([{type: '-', name: 'aaa'}, {type: 'd', name: 'bbb'}]).to.include.values('aaa');
8
- });
9
- });