guacamole 源码_guacamole实现RDP的下载
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
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 源码_guacamole实现RDP的下载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据中台和数仓的关系
- 下一篇: 解决Could not find met