基於 Nextcloud 的二次開發


Nextcloud 是個不錯的網盤系統,開源免費,支持 Windows Ad 域,而且開放了很多接口可以用於二次開發。

最近基於 Nextcloud 做了幾個二次開發的功能,下面介紹一下過程。

第一個需求是和公司業務系統對接起來,實現建立項目時自動為項目負責人建立一個同名文件夾和子文件夾。
第二個需求是開放一個頁面,可以瀏覽項目文件夾里的子文件夾、文件等。
第三個需求是可以在開放頁面下載列出的文件。

先看第一個需求,我需要做一個接口給業務系統,入參為項目名稱的人員唯一信息和項目名稱。
Nextcloud 有現成的建立文件夾方法,預想會很順利。但還是遇到了問題。
由於公司使用的 Windows Ad 域,我是獲取不到項目負責人的密碼的,所以不能使用項目負責人的帳號去建立文件夾。
然后靈光一閃,我可以使用一個固定的帳號(如:新建個帳戶 Administrator)去建立這個文件夾,然后把這個文件夾分享給項目負責人,並分配一定的權限。
但是在找人的步驟又遇到了困難,因為沒有表存域帳號。翻來翻去,在 oc_accounts 表里找到了郵箱信息,員工的郵箱基本上都是唯一的,所以可以用這個。
第一個需求方案差不多了,部份(偽)代碼如下:

var sql = $"select * from oc_accounts where data like '%\"{email}\"%'"; //查找要分享的用戶
oc_accounts[] rst = conn.Query<oc_accounts>(sql).ToArray();
if(l.Length < 1)
    return (false, null, $"網盤沒有找到您提供的域帳號或郵箱"); //沒找到要分享的人,直接返回錯誤
if(l.Length > 1)
    return (false, null, $"網盤找到了多個用戶,請確認您提供的郵箱地址正確!");//找到多個也不行
var cre = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{Adminitrator}:{密碼}"));//固定帳號的登錄名和密碼
(result, header, statusCode) = ExtMethods.ProcessRequest(null, $"{網盤域名}/remote.php/dav/files/{Administrator的根目錄(可在oc_ldap_user_mapping表查詢)}/{folderName}", new Dictionary<string, string>() { { "Authorization", $"Basic {cre}" } }, "MKCOL", null, null);//這個是 Nextcloud 提供的接口,用來建立文件夾。

上邊是建立文件夾,然后是分享部分:

var url = $"{網盤域名}/ocs/v2.php/apps/files_sharing/api/v1/shares";//接口地址
var inputHeader = new Dictionary<string, string>() { { "OCS-APIRequest", "true" }, { "Authorization", $"Basic {cre}" }, { "Content-Type", $"multipart/form-data; } };
string body = $"shareType=0&shareWith={shareWith}&permissions=31&path={path}";
//shareWith 是要分享的人,permissions 是權限,31是最大權限;path 是要分享的路徑
(result, header, statusCode) = ExtMethods.ProcessRequest(System.Text.Encoding.UTF8.GetBytes(body), url, inputHeader, "POST", null, null);//調用接口

建立子文件夾方法和上邊的一樣,很簡單,只是使用同步的方法建立的話,時間太長了,后來就做成了,建立主文件夾成功就啟動另外一個線程來建立子文件夾,然后就返回了。

subFolders = SubFolders.Select(x => folderName + "/" + x).ToArray();
Thread thread = new Thread(new ThreadStart(DoCreateSubFolders));
thread.Start();

private string[] subFolders;
private void DoCreateSubFolders()
{
    if(subFolders !=null && subFolders.Length > 0)
    {
        foreach(var s in subFolders)
        {
           CreateFolder(s);
        }
    }
}

第二個需求是列出文件夾的目錄,這個先用他們的接口試了試,結果速度太慢了,有點不能接受,后來改成了直接讀庫。

方案改了之后很順利,因為 Administrator 用戶是固定的,只要在 oc_ldap_user_mapping 表里找到根目錄就行了。

var storage = Ioc_StoragesService.GetModelByUserGuid(Administrator根路徑);
var rst = Ioc_FilecacheService.GetModelByStorage(storage.numeric_id, folderName);
return rst.Select(x => new OcFileEntity(x, 網盤地址, Request.Scheme + "://" + Request.Host.Value)).ToArray();

第三個需求是下載文件。

由於Nextcloud 本身的下載是需要身份驗證的,所以轉發肯定是不能用的。然后就想到了,先把文件下載下來,再返回給用戶。

WebClient wc = new WebClient();
wc.Headers.Add(HttpRequestHeader.Authorization, $"Basic {cre}");
var folder = System.IO.Path.GetDirectoryName(localpath);

wc.DownloadFile($"{網盤地址}/remote.php/dav/files/{Administrator根目錄}/{path}", localpath);

var sr = new FileStream($"{臨時文件夾}/" + path, FileMode.Open);
return File(sr, "application/octet-stream", Path.GetFileName(path), true);

這種實現方法要求站點部署時要和網盤服務器近一點(最好是同一台機器)。

歡迎同樣對 Nextcloud 做二次開發的朋友們來交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM