通过使用SSH,你可以把所有传输的数据进行加密,这样"中间人"这种攻击方式就不可能实现了,而且也能够防止DNS欺骗和IP欺骗。使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。
所谓“中间人”的攻击方式, 就是“中间人”冒充真正的服务器接收你传给服务器的数据,然后再冒充你把数据传给真正的服务器。服务器和你之间的数据传送被“中间人”一转手做了手脚之后,就会出现很严重的问题。
在上传之前,我们要获取这几个参数:
在前端调用 Meteor.call,通知服务端相应的上传方法,并把上述参数传给服务端,去做上传
1、实现上传(下载)我们需要借助一个依赖包ssh2-sftp-client。
所以先下载它。
npm install ssh2-sftp-client
2、引入
let sftpClient = require('ssh2-sftp-client');
3、创建一个sftp对象
let sftp = new sftpClient();
4、上传的过程
sftp.connect({ host: '127.0.0.1', port: '8080', username: 'username', password: '******' }).then(() => { return sftp.fastPut(localPath,remotePath, {step: (total_transferred, chunk, total) => { //每小段上传完成后的回调 }}) }) .then(data => { console.log( '上传结束',data); sftp.end(); }).catch(err => { console.log('上传出现错误',err); sftp.end(); });
fastPut(localPath, remotePath, options) ==> string
fastPut方法共有三个参数
localPath为本地文件的路径
remotePath为远程的路径(目的地的路径)
options为配置对象
options共有四个属性,其中step属性的值是一个方法。文件上传操作并不是一次性完成的,而是将一个大文件分成一小块一小块上传,所以每一小块上传完成后就调用一次这个方法。
在上传过程中会多次调用这个step方法。
step方法共有三个参数
3)当全部上传完成后,就执行第二个then中的回调方法。
回调的参数data是一个字符串,告诉你上传的结果,文件从哪上传到哪成功了。例如‘ E:\work\sg2148_MPanelCtl\img\Diagonal-45FoV-left.bmp was successfully uploaded to /opt/seeing/app/rgb_config/images/Diagonal-45FoV-left.bmp!’
在里面调用end方法,结束ssh
4)当catch到error时也end结束ssh。
5、下载的过程
下载的过程同上传的过程类似
let sftp = new sftpClient(); sftp.connect(server).then(() => { return sftp.fastGet(remotePath, localPath,{step: (total_transferred, chunk, total,) => { //每小段下载完成后的回调 }}); }).then(() =>{ console.log("下载结束"); sftp.end(); }).catch((err) => { console.log('下载出现错误',err); sftp.end(); });
下载使用的是sftp.fastGet方法,并且其参数的顺序与上传不同
第一个参数是远程的路径
第二个参数是本地的路径
总之无论上传还是下载方法,其第一个参数都是从哪里的地址,第二个参数是到哪里的地址。
上传一个文件是分多块上传的,每上传一小块就调用一次step函数。并且step函数的参数中含有已经上传完成的体积大小。
在服务端每次调用step函数时,都将上传的进度更新到数据库;然后在前端向数据库轮询,当上传完成时resolve出去。
但我在项目中发现,服务端更新数据库有时会存在bug,数据更新不上,即使改成递归的更新数据库(即更新数据库不成功,就再次更新,直到更新成功为之),但还是偶尔有问题。
服务端在step函数中向前端发消息,在传输完成时向前端发消息,在传输遇到错误时向前端发消息;前端根据这些消息做相应的处理。具体操作已在另一篇文章详述。