問題來源

文件服務(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說明里面有如下文字:

https://msdn.microsoft.com/zh-cn/windows/uwp/files/file-access-permissions#a-nameaccessing-additional-locationsa訪問其他位置

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓 

實現(xiàn):

1,添加權(quán)限

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

2,添加文件類型關(guān)聯(lián)

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

3,文件服務(wù)器文件操作(必須事先將文件服務(wù)器的認證信息保存在Window憑據(jù)里

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

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);
        }
    }

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

缺點:

  • 用戶固定無法自由切換

  • 無法查看全部文件

  • 在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é)議IPXNetBEUI 之上。

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)原理如下:

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

Windows系統(tǒng)本身就是一個SMB服務(wù)器,支持版本如下:

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

除了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的方法

讀取文件夾列表:

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

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")}"); 
}

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

讀取文件:

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

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()));

iOS培訓,Swift培訓,蘋果開發(fā)培訓,移動開發(fā)培訓

創(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 技巧

標簽: UWPSMBShareFolderJCIFSCIFS

http://www.cnblogs.com/lixiaobin/p/SMBShareFolder.html