問題來源
文件服務(wù)器文件夾操作在PC與Surface端確實還是和傳統(tǒng)操作一樣沒什么區(qū)別,但是到了手機端與Surface Hub就沒那么方便了,因為文件資源管理器Explorer根本沒法添加網(wǎng)路硬盤。對于傳統(tǒng)行業(yè)以及擔心云端文件安全的企業(yè)固然還是希望能使用文件服務(wù)器,特別是SurfaceHub用戶。SurfaceHub用戶開會的時候會用到很多敏感文件,這個時候如果無法訪問內(nèi)部機密文件服務(wù)器,那還有什么用處?
解決方法
由于SurfaceHub只能安裝UWP應(yīng)用,自然首先考慮UWP的實現(xiàn)。目前支持SurfaceHub的應(yīng)用只有Yuki Explorer與Metro commander,Total Commander暫時不支持。兩者也許是使用了以下提到的開源項目SharpCifs??
方法一:文件類型關(guān)聯(lián)(只支持單個用戶與Guest用戶)
文件服務(wù)器文件路徑其實就是UNC路徑,在StorageFolder說明里面有如下文字:
實現(xiàn):
1,添加權(quán)限
2,添加文件類型關(guān)聯(lián)
3,文件服務(wù)器文件操作(必須事先將文件服務(wù)器的認證信息保存在Window憑據(jù)里)
public class ShareFolderService { /// <summary> /// get items from unc path /// *you must add the /// </summary> /// <param name="uncPath"></param> /// <returns></returns> public async Task<IReadOnlyList<IStorageItem>> GetShareFolderItemsAsync(string uncPath) { var folder = await getFolderFromUncPath(uncPath); return await folder.GetItemsAsync(); } /// <summary> /// create item to share folder /// </summary> /// <param name="uncPath"></param> /// <param name="name"></param> /// <param name="isFile"></param> /// <returns></returns> public async Task<IStorageItem> ShareFolderCreateItemAsync(string uncPath, string name, bool isFile = true) { var shareFolder = await getFolderFromUncPath(uncPath); if (isFile) { return await shareFolder.CreateFileAsync(name, CreationCollisionOption.ReplaceExisting); } else { return await shareFolder.CreateFolderAsync(name, CreationCollisionOption.OpenIfExists); } } private async Task<StorageFolder> getFolderFromUncPath(string uncPath) { return await StorageFolder.GetFolderFromPathAsync(uncPath); } }
缺點:
用戶固定無法自由切換
無法查看全部文件
在SurfaceHub端將導(dǎo)致雙擊文件無法啟動(SurfaceHub Bug)
方法二:SMB協(xié)議實現(xiàn)(支持全部用戶)
概述:
服務(wù)器信息塊(SMB)協(xié)議是一種IBM協(xié)議,用于在計算機間共享文件、打印機、串口等。SMB 協(xié)議可以用在因特網(wǎng)的TCP/IP協(xié)議之上,也可以用在其它網(wǎng)絡(luò)協(xié)議如IPX和NetBEUI 之上。
SMB 一種客戶機/服務(wù)器、請求/響應(yīng)協(xié)議。通過 SMB 協(xié)議,客戶端應(yīng)用程序可以在各種網(wǎng)絡(luò)環(huán)境下讀、寫服務(wù)器上的文件,以及對服務(wù)器程序提出服務(wù)請求。此外通過 SMB 協(xié)議,應(yīng)用程序可以訪問遠程服務(wù)器端的文件、以及打印機、郵件槽(mailslot)、命名管道(named pipe)等資源。
在 TCP/IP 環(huán)境下,客戶機通過 NetBIOS over TCP/IP(或 NetBEUI/TCP 或 SPX/IPX)連接服務(wù)器。一旦連接成功,客戶機可發(fā)送 SMB 命令到服務(wù)器上,從而客戶機能夠訪問共享目錄、打開文件、讀寫文件,以及一切在文件系統(tǒng)上能做的所有事情。
從 Windows 95 開始,Microsoft Windows 操作系統(tǒng)(operating system)都包括了客戶機和服務(wù)器 SMB協(xié)議支持。Microsoft 為 Internet 提供了 SMB 的開源版本,即通用 Internet 文件系統(tǒng) (CIFS)。與現(xiàn)有 Internet 應(yīng)用程序如文件傳輸協(xié)議(FTP)相比, CIFS 靈活性更大。對于 UNIX 系統(tǒng),可使用一種稱為 Samba 的共享軟件。
Windows的Explorer實現(xiàn)原理如下:
Windows系統(tǒng)本身就是一個SMB服務(wù)器,支持版本如下:
除了Windows系統(tǒng)以外,UNIX與Mac或者Android系統(tǒng)都可以安裝SMB軟件訪問各類文件服務(wù)器系統(tǒng)的文件。
JAVA開源項目:JCIFS
JCIFS 是一個純 JAVA 編寫的實現(xiàn) CIFS/SMB 協(xié)議的開源項目。它由 samba 組織負責維護開發(fā)。 JCIFS 是一個完整的,豐富的,具有可擴展能力且線程安全的客戶端庫。這一庫可以應(yīng)用于各種 JAVA 虛擬機訪問遵循 CIFS/SMB 網(wǎng)絡(luò)傳輸協(xié)議的網(wǎng)絡(luò)資源,包括 Windows 下的共享資源和 Linux & Unix 下的 SAMBA 資源。
.NET開源項目:
SharpCifs :從JCIFS轉(zhuǎn)換而來,支持Windows Phone 8.1 (Silverlight) 。
SharpCifs.Std :從SharpCifs轉(zhuǎn)換而來,支持Xamarin & .NET Core 。Nuget包:Install-Package SharpCifs.Std –Pre
實現(xiàn):
主要使用SharepCifs.Std來實現(xiàn)。由于SharepCifs.Std類庫使用了UWP不支持的包:
System.Console (>= 4.3.0)
System.Threading.Thread (>= 4.3.0)
所有需要將以上兩個包做替換處理:
System.Console (>= 4.3.0)關(guān)聯(lián)的Console.Error與Console.Write方法替換為StringWriter的Write方法
System.Threading.Thread (>= 4.3.0) 替換成Task方法(CurrentThread方法可以為空)
Dns.GetHostName()需要替換回SharepCifs的方法
讀取文件夾列表:
var folder = new SmbFile("smb://UserName:Password@ServerName/ShareName/Folder/")); var epocDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);foreach (var item in folder.ListFiles()) { var lastModDate = epocDate.AddMilliseconds(item.LastModified()).ToLocalTime(); Log.WriteLine($"Name: {item.GetName()}, isDir?: {item.IsDirectory()}, Date: {lastModDate.ToString("yyyy-MM-dd HH:mm:ss")}"); }
讀取文件:
var file = new SmbFile("smb://UserName:Password@ServerName/ShareName/Folder/FileName.txt"));var readStream = file.GetInputStream();var buffer = new byte[1024*8];var memStream = new MemoryStream();int size;while ((size = readStream.Read(buffer, 0, buffer.Length)) > 0) memStream.Write(buffer, 0, size); Log.WriteLine(Encoding.UTF8.GetString(memStream.ToArray()));
創(chuàng)建文件:
var file = new SmbFile("smb://UserName:Password@ServerName/ShareName/Folder/NewFileName.txt")); file.CreateNewFile();var writeStream = file.GetOutputStream(); writeStream.Write(Encoding.UTF8.GetBytes("Hello!"));
優(yōu)點:
由于需要用戶名與密碼所有支持所有用戶(含Guest)
支持所有設(shè)備(SurfaceHub,Android,iOS等)
支持所有文件類型
備注:
目前打算將次代碼轉(zhuǎn)換為PCL類庫,以供在Xamarin項目中實現(xiàn)。
每天成就一小步,積累下來就是一大步。 轉(zhuǎn)發(fā)本文請注明出處,謝謝您的閱讀與分享!
分類: Xamarin,Xamarin.Forms,C#.NET,UWP探討,visual studio 技巧
標簽: UWP, SMB, ShareFolder, JCIFS, CIFS
http://www.cnblogs.com/lixiaobin/p/SMBShareFolder.html