1. 配置说明

1.1 主要特别配置以下三项

enable-drive

默认情况下禁用文件传输,但启用文件传输后,RDP用户可以将文件传输到持久存在于Guacamole服务器上的虚拟驱动器。通过将此参数设置为“true”来启用文件传输支持。文件将存储在由“ drive-path”参数指定的目录中,如果启用了文件传输,则该参数是必需的。

drive-path|Guacamole

服务器上应存储传输文件的目录。该目录必须对guacd可访问,并且对运行guacd的用户可读写。此参数不指RDP服务器上的目录。如果文件传输未启用,则此参数将被忽略。

create-drive-path

如果设置为“true”,并且启用了文件传输,drive-path指定的目录将自动创建。将只创建路径中的最终目录 - 如果路径之前的其他目录不存在,则自动创建将失败,并会记录错误。默认情况下,该drive-path参数指定的目录 将不会自动创建,并且尝试将文件传输到不存在的目录将被记录为错误。

如果文件传输未启用,则此参数将被忽略。

  • 参考配置
enable-drive = true
drive-path = '/yourpath'
create-drive-path = true

在浏览器登录到堡垒机,可以看到设备和驱动里面多了一个guacamole RDP驱动

以下是截图

进入驱动下

理解:

实际上在使用RDP协议的时候,有下面的关系。

浏览器<->guacamole服务器<->真实服务器

我们看到的guacamole RDP,指向的是guacamole服务器的 /yourpath文件夹,你把文件拖动到这个驱动下,就把文件上传到guacamole服务器的 /yourpath目录下了,接下来我们可以通过浏览器下载guacamole服务器的文件,这个需要自己去实现。特别注意,发现有个download文件夹,默认存在并且不能删除掉,作用就是你在堡垒机上操作把文件拖进去,会向浏览器发送file命令(如下图所示),然后我们可以在cilent端进行监听,然后实现拖动自动下载。

2. 源码分析实现

2.1 把指令转换成相应的client操作


/**
* Handlers for all instruction opcodes receivable by a Guacamole protocol
* client.
* @private
*/
var instructionHandlers = {
...其它指令 "file": function(parameters) { //处理参数
var stream_index = parseInt(parameters[0]);
var mimetype = parameters[1];
var filename = parameters[2]; // Create stream
if (guac_client.onfile) {
//这里根据index得到了输入流的抽象,注意下InputStream方法
var stream = streams[stream_index] = new Guacamole.InputStream(guac_client, stream_index);
//创建完流之后,调用了client的onfile方法,并且把参数传递过去,我们需要在client的onfile方法里面处理输入的流。
guac_client.onfile(stream, mimetype, filename);
} // Otherwise, unsupported
else
guac_client.sendAck(stream_index, "File transfer unsupported", 0x0100); }, ...其它指令
}

以下是InputStream的代码,实际上是进行了一些属性的初始化工作


/**
* An input stream abstraction used by the Guacamole client to facilitate
* transfer of files or other binary data.
*
* @constructor
* @param {Guacamole.Client} client The client owning this stream.
* @param {Number} index The index of this stream.
*/
Guacamole.InputStream = function(client, index) { /**
* Reference to this stream.
* @private
*/
var guac_stream = this; /**
* The index of this stream.
* @type {Number}
*/
this.index = index; /**
* Called when a blob of data is received.
*
* @event
* @param {String} data The received base64 data.
*/
this.onblob = null; /**
* Called when this stream is closed.
*
* @event
*/
this.onend = null; /**
* Acknowledges the receipt of a blob.
*
* @param {String} message A human-readable message describing the error
* or status.
* @param {Number} code The error code, if any, or 0 for success.
*/
this.sendAck = function(message, code) {
client.sendAck(guac_stream.index, message, code);
}; };

2.2 client的onfile方法

这个自己实现,作用就是监听上面的onfile事件,并进一步处理

    client.onfile = function(stream, mimetype, filename){
//通知服务端,已经收到了stream
stream.sendAck('OK', Guacamole.Status.Code.SUCCESS);
//开始处理输入流,这里封装了一个downloadFile方法
downloadFile(stream, mimetype, filename);
}

2.3 处理输入流的逻辑

downloadFile = (stream, mimetype, filename) => {
//拿到的流不能直接使用,先实例化一个处理器,使用blob reader处理数据
var blob_builder;
if (window.BlobBuilder) blob_builder = new BlobBuilder();
else if (window.WebKitBlobBuilder) blob_builder = new WebKitBlobBuilder();
else if (window.MozBlobBuilder) blob_builder = new MozBlobBuilder();
else
blob_builder = new (function() { var blobs = []; /** @ignore */
this.append = function(data) {
blobs.push(new Blob([data], {"type": mimetype}));
}; /** @ignore */
this.getBlob = function() {
return new Blob(blobs, {"type": mimetype});
}; })(); // Append received blobs
stream.onblob = function(data) { // Convert to ArrayBuffer
var binary = window.atob(data);
var arrayBuffer = new ArrayBuffer(binary.length);
var bufferView = new Uint8Array(arrayBuffer); for (var i=0; i<binary.length; i++)
bufferView[i] = binary.charCodeAt(i); //收到后就交给blob_builder
blob_builder.append(arrayBuffer);
length += arrayBuffer.byteLength; // Send success response
stream.sendAck("OK", 0x0000); }; stream.onend = function(){
//结束的时候,获取blob_builder里面的可用数据
var blob_data = blob_builder.getBlob(); //数据传输完成后进行下载等处理
if(mimetype.indexOf('stream-index+json') != -1){
//如果是文件夹,使用filereader读取blob数据,可以获得该文件夹下的文件和目录的名称和类型,是一个json形式
var blob_reader = new FileReader();
blob_reader.addEventListener("loadend", function() {
let folder_content = JSON.parse(blob_reader.result)
//重新组织当前文件目录,appendFileItem是自己封装的文件系统动态展示
appendFileItem(folder_content)
$("#header_title").text(filename);
});
blob_reader.readAsBinaryString(blob_data);
} else {
//如果是文件,直接下载,但是需要解决个问题,就是如何下载blob数据
//借鉴了https://github.com/eligrey/FileSaver.js这个库
var file_arr = filename.split("/");
var download_file_name = file_arr[file_arr.length - 1];
saveAs(blob_data, download_file_name);
}
}
}

guacamole实现RDP的下载的更多相关文章

  1. guacamole实现上传下载

    目录 1. 源码解读 2. 上传下载的核心代码 分析的入手点,查看websocket连接的frame 看到首先服务端向客户端发送了filesystem请求,紧接着浏览器向服务端发送了get请求,并且后 ...

  2. 搭建 Guacamole 并解决各种坑和创建不了虚拟驱动器导致无法实现文件传输的方法

    系统类型版本:centos7 64位 结果:最终跑通了项目并且实现了虚拟驱动器的文件传输功能,添加了中文支持 反思总结: 先查看官方文档的Q&A,找找有没有类似的错误,然后如果有错误日志或者现 ...

  3. Guacamole 介绍

    Guacamole 介绍以及架构   目前在从事一些虚拟化解决方案方面的工作,最近项目有需求,希望能在浏览器上远程操作虚拟机. 此时发现了Guacamole,一个提供远程桌面的解决方案的开源项目,通过 ...

  4. CUDA/CUDNN下载安装以及适配pytorch和tensorflow

    CUDA以及CUDNN下载安装 在https://developer.nvidia.com/cuda-toolkit-archive可以找到各个版本的cuda,个人建议下载cuda11.0(也就是2年 ...

  5. Centos7.4下安装Jumpserver 1.0.0(支持windows组件)

    0)系统环境CentOS 7.4 IP: 192.168.100.10 [root@jumpserver-server ~]# cat /etc/redhat-release CentOS Linux ...

  6. Centos7.3下安装Jumpserver 1.0.0(支持windows组件)

    Jumpserver最新版本支持windows组件,废话不多介绍了,下面直接介绍下部署过程: 0)系统环境 CentOS 7.3 IP: 192.168.10.210 [root@jumpserver ...

  7. Jumpserver 5.2版本安装与部署

    组件说明 Jumpserver 为管理后台, 管理员可以通过 Web 页面进行资产管理.用户管理.资产授权等操作, 用户可以通过 Web 页面进行资产登录, 文件管理等操作 koko 为 SSH Se ...

  8. 使用开源软件 jumpserver 搭造自己的堡垒机

    使用开源软件 jumpserver 搭造自己的堡垒机 开软地址:https://github.com/jumpserver/jumpserver 目前版本:1.5.2 测试的时候有少许BUG,但功能却 ...

  9. jumpserver-1.4.8安装步骤

    1. 组件说明 Jumpserver 为管理后台, 管理员可以通过 Web 页面进行资产管理.用户管理.资产授权等操作, 用户可以通过 Web 页面进行资产登录, 文件管理等操作 koko 为 SSH ...

随机推荐

  1. iOS系统声音列表

    iOS系统声音列表 效果 说明 1. 点击cell就能发出声音 2. 只需要给出声音编号,就可以,非常简单易用 源码 https://github.com/YouXianMing/iOS-Utilit ...

  2. Python入门-模块2(random模块、os模块)

    >>> random.randomrange(1,10) #返回1-10之间的一个随机数,不包括10 >>> random.randint(1,10) #返回1-1 ...

  3. 企业大数据之Elasticsearch的搜索类型

    下面的 ES基于版本(V2.3.4) ES之默认 1.默认自动发先同一局域网的所有集群节点 2.默认一个索引库会有5个分片,(分片越多,效率越好) 由于这两个默认,所以统一索引库的分片对分布在不同机器 ...

  4. HNOI2018退役记

    不想记流水账了,总结一下考炸的原因吧.. $day1$: $12$点才知道$t3$怎么做. 可以用容斥+动态$dp$来搞,但是没时间写了. 事实上这个方法也比较复杂,标算比这优美多了. 所以还是想得太 ...

  5. wk_06.md

    IO与文件操作 文件内建函数open 内建函数open提供了初始化输入/输出(I/O)操作的通用接口.open()内建函数成功打开文件后会返回一个文件对象.open函数的语法如下: open(file ...

  6. python第五课——流程控制语句

    流程控制语句: 分类: 1).顺序结构 2).判断结构解析:如果...否则... 3).循环结构 1.判断结构: 格式分类:三种格式 格式一: ① if 条件表达式: 语句块 ② 执行流程: 计算机会 ...

  7. was集群下基于接口分布式架构和开发经验谈

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/luozhonghua2014/article/details/34084935    某b项目是我首 ...

  8. 【转】decorView和window之间的层级及关系

    转载请注明出处:http://blog.csdn.net/guxiao1201/article/details/41744107 首先贴出实现Activity对话框圆角的核心代码 @Override ...

  9. Java并发编程--2.synchronized

    前言 synchronized关键字是互斥锁,也称为内部锁 每个对象都有自己的monitor(锁标记),它是为了分配给线程,最多一个线程可以拥有对象的锁 使用 synchronized修饰成员方法,锁 ...

  10. HBase学习之路 (四)HBase的API操作

    Eclipse环境搭建 具体的jar的引入方式可以参考http://www.cnblogs.com/qingyunzong/p/8623309.html HBase API操作表和数据 import ...