crashzero
Goto Top

Nextcloud Dateiübertrag mit Freigabelink und Schlagwortsetzung

Moin,

ich hoffe mir kann jemand weiterhelfen.
Seid kurzem arbeite ich mit MS Visual Studio 22 Community und erstelle kleine Programme mit Windows Forms-App.

Nun zu meinem Problem.

Ich habe eine Form erstellt die eine (bereits erstellte name.zip Datei) enthält welche via await uploader auch erfogreich auf den Nextcloudserver in ein bestimmtes Verzeichnis (Anmeldedaten im Script enthalten) hochgeladen wird.

Nun soll , via API, für die hochgeladene Datei ein Freigabelink (Öffentlich, nur lesen) mit einem Downloadpasswort (Zufallsgeneriert) und ein Schlagwort auf die Freigabe/Datei generiert und der Freigabelink in einer variabel im Script dann abgelegt werden für den späteren Gebrauch.

Der Nextcloudserver ist ein Nextcloud Hub 9 (30.0.0)

Ablauf : Form mit Button und prozesstextbox - Beim Klick auf den Button wird die Datei hochgeladen, Freigabelink generiert, Downloadpasswort gesetzt, Verschlagwortung gesetzt.

Bisher funktioniert :
1. Hochladen i.O.
2. Freigabelink setzen (Sieht man aber nur auf dem NC und wird auch nicht im Script ausgelesen bzw. angezeigt) Teilweise i.O.
3. Downloadpasswort setzen i.O.
4. Verschlagwortung funktioniert nicht, da meine App den Freigabelink (Vermute ich mal) nicht kennt bzw. zurückgemeldet wird.
5. Ablaufdatum für die Freigabe i.O.

Ich habe also ALLE Meldungen die erzeugt werden (Meine APP sowie die Rückmeldungen der NC-API in eine Datei umgeleitet) und siehe da, dort steht der Freigabelink drin und funktioniert auch mit dem Downloadpasswort.

Allerdings steht dort auch ein Fehler mit dem ich nix anfangen kann.
Ich vermute das es etwas mit der Zeile <Path>........</Path> zu tun hat ?
Log-Datei :
20.11.2024 12:27:40: Hochladen zur Nextcloud läuft ...
20.11.2024 12:27:48: Datei erfolgreich hochgeladen!
20.11.2024 12:27:48: Antwort des Servers: <?xml version="1.0"?>  
<ocs>
 <meta>
  <status>ok</status>
  <statuscode>200</statuscode>
  <message>OK</message>
 </meta>
 <data>
  <id>52</id>
  <share_type>3</share_type>
  <uid_owner>name</uid_owner>
  <displayname_owner>Name</displayname_owner>
  <permissions>1</permissions>
  <can_edit>1</can_edit>
  <can_delete>1</can_delete>
  <stime>1732102096</stime>
  <parent/>
  <expiration>2024-11-25 00:00:00</expiration>
  <token>Tokennummer ctn53mdgb</token>
  <uid_file_owner>name</uid_file_owner>
  <note></note>
  <label></label>
  <displayname_file_owner>Name</displayname_file_owner>
  <path>/UNTERORDNER/Datei.zip</path>
  <item_type>file</item_type>
  <item_permissions>27</item_permissions>
  <mimetype>application/zip</mimetype>
  <has_preview></has_preview>
  <storage_id>home::name</storage_id>
  <storage>5</storage>
  <item_source>8556</item_source>
  <file_source>8556</file_source>
  <file_parent>690</file_parent>
  <file_target>/Datei.zip</file_target>
  <item_size>17606910</item_size>
  <item_mtime>1732102096</item_mtime>
  <share_with>3|$argon2id$v=19$m=65536,t=4,p=2$5yQnBHgTrrFp65kgNyw$yNg6nKyHHXWd+SdCztjffbq06x1uLM7YFm2ABp5GQO0</share_with>
  <share_with_displayname>(Geteilter Link)</share_with_displayname>
  <password>3|$argon2id$v=19$m=65536,t=4,p=2$5yQnBHgTrrFp65kgNyw$yNg6nKyHHXWd+SdCztjffbq06x1uLM7YFm2ABp5GQO0</password>
  <send_password_by_talk></send_password_by_talk>
  <url>https://domainname/nextcloud/index.php/s/SAWRK5jok6kfw3B</url>
  <mail_send>1</mail_send>
  <hide_download>0</hide_download>
  <attributes/>
 </data>
</ocs>

20.11.2024 12:27:48: Fehler beim Erstellen der Freigabe: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.  

Mein C-Code sieht so aus :
(Der ist jetzt nicht wirklich sauber da ich schon viel zusätzlich eingetragen habe um an das Problem zu kommen)
(Habt ein wenig Rücksicht, ich habe schon viel probiert, Tag setzen nach der Freigabe, Freigabelink aus der log-extrahieren usw., daher bereits sehr unübersichtlich, außerdem bin ich blutiger Anfänger)

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using System.Text.RegularExpressions;

namespace TestfreigabeNC
{
    public partial class Form1 : Form
    {
        private NextcloudUploader uploader; // Instanz der NextcloudUploader-Klasse

        public Form1()
        {
            InitializeComponent();
            uploader = new NextcloudUploader(prozesstextBox1); // Instanz mit Status-Textbox erstellen
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            // Beispielwerte für die Parameter
            string zipFilePath = @"c:\Freigabe\TemporaerDaten\Datei.zip"; // Lokaler Pfad  
            string ncordnername = "UNTERORDNER";            // Ordnername in Nextcloud  
            string dateiname = "Datei.zip"; // Dateiname in Nextcloud  
            string ocUrl = "https://domainname.de/nextcloud"; // Nextcloud-Basis-URL  
            string ncpassword2 = "1234567890";    // Passwort für die Freigabe  
            string ncablaufdatum = "2024-11-25"; // Ablaufdatum der Freigabe  

            try
            {
                // Hochladen und Freigabe erstellen
                await uploader.UploadFileToNextcloud(zipFilePath, ncordnername, dateiname, ocUrl, ncpassword2, ncablaufdatum);
            }
            catch (Exception ex)
            {
                // Fehlerbehandlung
                MessageBox.Show($"Fehler: {ex.Message}", "Fehler beim Hochladen", MessageBoxButtons.OK, MessageBoxIcon.Error);  
                uploader.LogMessage($"Fehler: {ex.Message}");  
            }
        }
    }

    public class NextcloudUploader
    {
        private TextBox _statusTextBox;

        // Konstruktor: TextBox zur Anzeige des Fortschritts übergeben
        public NextcloudUploader(TextBox statusTextBox)
        {
            _statusTextBox = statusTextBox;
        }

        public async Task UploadFileToNextcloud(string zipFilePath, string ncordnername, string dateiname, string ocUrl, string ncpassword2, string ncablaufdatum)
        {
            if (File.Exists(zipFilePath))
            {
                string nextcloudUrl = "https://domainname/nextcloud/remote.php/dav/files/name/UNTERORDNER/";  
                string username = "name";  
                string passwordNextcloud = "passwort";  

                UpdateStatus("Hochladen zur Nextcloud läuft ...");  
                LogMessage("Hochladen zur Nextcloud läuft ...");  

                using (var client = new HttpClient())
                {
                    // Authentifizierung für die HTTP-Anfrage
                    var authToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{passwordNextcloud}"));  
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authToken);  

                    // Zusätzlicher Header für die OCS-API
                    client.DefaultRequestHeaders.Add("OCS-APIREQUEST", "true");  

                    using (var fileStream = File.OpenRead(zipFilePath))
                    {
                        var content = new StreamContent(fileStream);
                        content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");  
                        string targetUrl = nextcloudUrl + Path.GetFileName(zipFilePath);

                        // Datei hochladen
                        var response = await client.PutAsync(targetUrl, content);

                        if (response.IsSuccessStatusCode)
                        {
                            UpdateStatus("Datei erfolgreich hochgeladen!");  
                            LogMessage("Datei erfolgreich hochgeladen!");  

                            // Erstellen der Freigabe nach erfolgreichem Upload
                            var shareUrl = $"{ocUrl}/ocs/v2.php/apps/files_sharing/api/v1/shares";  

                            // Erstellen der Freigabeparameter
                            var shareRequestData = new FormUrlEncodedContent(new[]
                            {
                                new KeyValuePair<string, string>("path", $"{ncordnername}/{dateiname}"),  
                                new KeyValuePair<string, string>("shareType", "3"), // Öffentliche Freigabe  
                                new KeyValuePair<string, string>("password", ncpassword2),  
                                new KeyValuePair<string, string>("permissions", "1"), // Leseberechtigung  
                                new KeyValuePair<string, string>("expireDate", ncablaufdatum)  
                            });

                            try
                            {
                                var shareResponse = await client.PostAsync(shareUrl, shareRequestData);

                                // Antwortinhalt als Rohtext ausgeben
                                var responseContent = await shareResponse.Content.ReadAsStringAsync();
                                UpdateStatus($"Antwort des Servers: {responseContent}");  // Protokollierung der Serverantwort  
                                LogMessage($"Antwort des Servers: {responseContent}");  

                                // Überprüfen des Statuscodes
                                if (shareResponse.IsSuccessStatusCode)
                                {
                                    dynamic shareResponseJson = JsonConvert.DeserializeObject(responseContent);

                                    // Freigabelink aus der Antwort extrahieren
                                    string publicLink = shareResponseJson?.ocs?.data?.url;
                                    UpdateStatus($"Datei erfolgreich freigegeben! Freigabelink: {publicLink}");  
                                    LogMessage($"Datei erfolgreich freigegeben! Freigabelink: {publicLink}");  

                                    // Schlagwort "2Tage" setzen 
                                    await SetTagOnFile(client);
                                }
                                else
                                {
                                    // Fehler bei der Freigabe
                                    UpdateStatus($"Fehler bei der Freigabe: {shareResponse.StatusCode}");  
                                    LogMessage($"Fehler bei der Freigabe: {shareResponse.StatusCode}");  
                                }
                            }
                            catch (Exception ex)
                            {
                                // Fehler beim Verarbeiten der Antwort
                                UpdateStatus($"Fehler beim Erstellen der Freigabe: {ex.Message}");  
                                LogMessage($"Fehler beim Erstellen der Freigabe: {ex.Message}");  
                            }
                        }
                        else
                        {
                            // Fehler beim Hochladen der Datei
                            UpdateStatus($"Fehler beim Hochladen: {response.StatusCode}");  
                            LogMessage($"Fehler beim Hochladen: {response.StatusCode}");  
                        }
                    }
                }
            }
            else
            {
                UpdateStatus("Die angegebene Datei existiert nicht!");  
                LogMessage("Die angegebene Datei existiert nicht!");  
            }
        }

        private async Task SetTagOnFile(HttpClient client)
        {
            // URL aus der Logdatei extrahieren
            string publicLink = GetUrlFromLogFile(@"c:\Freigabe\Log\nc.log");  
            if (!string.IsNullOrEmpty(publicLink))
            {
                string tagUrl = "https://domainname/nextcloud/ocs/v2.php/apps/files_tags/api/v1/tags";  
                var tagData = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair<string, string>("tag", "2Tage"),  
                    new KeyValuePair<string, string>("itemType", "file"),  
                    new KeyValuePair<string, string>("itemId", publicLink) // Die ID oder der Link der Datei  
                });

                try
                {
                    var tagResponse = await client.PostAsync(tagUrl, tagData);
                    if (tagResponse.IsSuccessStatusCode)
                    {
                        UpdateStatus("Schlagwort '2Tage' erfolgreich gesetzt!");  
                        LogMessage("Schlagwort '2Tage' erfolgreich gesetzt!");  
                    }
                    else
                    {
                        UpdateStatus("Fehler beim Setzen des Schlagworts '2Tage'.");  
                        LogMessage("Fehler beim Setzen des Schlagworts '2Tage'.");  
                    }
                }
                catch (Exception ex)
                {
                    UpdateStatus($"Fehler beim Setzen des Schlagworts: {ex.Message}");  
                    LogMessage($"Fehler beim Setzen des Schlagworts: {ex.Message}");  
                }
            }
            else
            {
                UpdateStatus("Kein gültiger Link in der Logdatei gefunden!");  
                LogMessage("Kein gültiger Link in der Logdatei gefunden!");  
            }
        }

        private string GetUrlFromLogFile(string logFilePath)
        {
            try
            {
                if (File.Exists(logFilePath))
                {
                    string logContent = File.ReadAllText(logFilePath);
                    Regex regex = new Regex(@"<url>(.*?)</url>", RegexOptions.IgnoreCase);  
                    Match match = regex.Match(logContent);
                    if (match.Success)
                    {
                        return match.Groups[1].Value;
                    }
                }
            }
            catch (Exception ex)
            {
                LogMessage($"Fehler beim Auslesen der Logdatei: {ex.Message}");  
            }
            return null;
        }

        // Hilfsmethode zur Aktualisierung der Statusanzeige
        private void UpdateStatus(string message)
        {
            if (_statusTextBox.InvokeRequired)
            {
                _statusTextBox.Invoke(new Action(() => _statusTextBox.Text = message));
            }
            else
            {
                _statusTextBox.Text = message;
            }
        }

        // Loggen von Nachrichten
        public void LogMessage(string message)
        {
            string logDirectory = @"c:\Freigabe\Log";  
            string logFile = Path.Combine(logDirectory, "nc.log");  

            try
            {
                if (!Directory.Exists(logDirectory))
                {
                    Directory.CreateDirectory(logDirectory);
                }

                if (!File.Exists(logFile))
                {
                    File.Create(logFile).Close();
                }

                using (StreamWriter writer = new StreamWriter(logFile, true))
                {
                    writer.WriteLine($"{DateTime.Now}: {message}");  
                }
            }
            catch (Exception ex)
            {
                UpdateStatus($"Fehler beim Loggen der Nachricht: {ex.Message}");  
            }
        }
    }
}


Hat ev. jemand eine Idee, bzw. kann mir auf die Sprünge helfen ?

Gruß

Content-ID: 669641

Url: https://administrator.de/forum/nextcloud-dateiuebertrag-mit-freigabelink-und-schlagwortsetzung-669641.html

Ausgedruckt am: 21.12.2024 um 15:12 Uhr

150940
150940 20.11.2024 aktualisiert um 13:19:42 Uhr
Goto Top
Soweit ich mich erinnere braucht es einen führenden Slash bei der Pfadangabe (Path-Parameter) der Erstellung des Shares.

Zur Tagvergabe guck ma hier Nextcloud-API Freigabelinkerstellung mit Tagübergabe
Crashzero
Crashzero 20.11.2024 aktualisiert um 16:30:01 Uhr
Goto Top
Jup, das war mal mein Thread, hab das ganze schon erfolgreich mit Powershell realisiert, läuft wunderbar.

Bin grad dran das ganze via C# um zu setzen.

Wo/was meinst du genau PATH mit / vorweg ?

In der Log-Datei wurde ja das richtige PATH Format zurückgemeldet :
<path>/UNTERORDNER/Datei.zip</path>
[Zeile 26 Log-Datei]

Ich gebe das / vor der Pfadangabe ja auch mit im Code.
Upload usw. funktioniert ja auch, auch im Log-File zu sehen ist ja zu dem Zeitpunkt ja bereits erfolgreich ein Freigabelink erstellt worden
  <url>https://domainname/nextcloud/index.php/s/SAWRK5jok6kfw3B</url>
[Zeile 43]

Ich bekomme den nur nicht direkt im Code zurückgeliefert.
Könnte jetzt den Freigabelink aus dem LOG-Extraieren aber das ist ja nicht der "schöne" weg.

Im Backend auf dem NC sehe ich auch diese Freigabe, das funktioniert bis dahin, nur das Rückliefern in meinen Code nicht.

Was definitiv nicht funktioniert ist das Setzen des Tags (Schlagwort), da habe ich irgendwie nen Fehler drin und finde den nicht.
150940
150940 20.11.2024 aktualisiert um 16:34:06 Uhr
Goto Top
Wo/was meinst du genau PATH mit / vorweg ?
hier beim Erstellen der Freigabe, nicht beim Hochladen: da fehlt er
new KeyValuePair<string, string>("path", $"{ncordnername}/{dateiname}"),   
bzw. in der Variablen, da fehlt er auch
string ncordnername = "UNTERORDNER";  
Crashzero
Crashzero 20.11.2024 um 16:37:34 Uhr
Goto Top
? ---- Sollte ich das wirklich übersehen haben ?

Ohman, ich schau mir das morgen mal an, wenn es das ist hab ich vermutlich für heute nicht rechtzeitig aufgehört zu coden ;)

Dann wundert mich das aber das die Freigabe und Freigabelink sowie Downloadpasswort geklappt haben .....

Wenn ich aus dem Log mir den Freigabelink kopiere, im Browser einsetze kommt die korrekte Passwortabfrage für den Download und danach ist die freigegebene Datei zu sehen.

Ich melde mich morgen nochmal dazu.

Danke dir.
Crashzero
Crashzero 21.11.2024 aktualisiert um 11:14:19 Uhr
Goto Top
Moinsen,

also hab folgendes probiert :
 string ncordnername = "UNTERORDNER";  

 string ncordnername = "/UNTERORDNER";  

new KeyValuePair<string, string>("path", $"/{ncordnername}/{dateiname}"),  

new KeyValuePair<string, string>("path/", $"{ncordnername}/{dateiname}"),  

new KeyValuePair<string, string>("/path", $"{ncordnername}/{dateiname}"),  

Der Fehler lautet immer :

21.11.2024 10:54:08: Fehler beim Erstellen der Freigabe: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.  

Ich denke aber auch das dies Problem in diesem Bereich besteht.

 // Erstellen der Freigabeparameter
                            var shareRequestData = new FormUrlEncodedContent(new[]
                            {
                                new KeyValuePair<string, string>("path", $"{ncordnername}/{dateiname}"),    
                                new KeyValuePair<string, string>("shareType", "3"), // Öffentliche Freigabe    
                                new KeyValuePair<string, string>("password", ncpassword2),    
                                new KeyValuePair<string, string>("permissions", "1"), // Leseberechtigung    
                                new KeyValuePair<string, string>("expireDate", ncablaufdatum)    
                            });

In der log steht aber soweit erfolg drin :

21.11.2024 10:53:37: Hochladen zur Nextcloud läuft ...
21.11.2024 10:54:07: Datei erfolgreich hochgeladen!
21.11.2024 10:54:08: Antwort des Servers: <?xml version="1.0"?>  
<ocs>
 <meta>
  <status>ok</status>
  <statuscode>200</statuscode>
  <message>OK</message>
 </meta>
 <data>
  <id>56</id>
  <share_type>3</share_type>
  <uid_owner>name</uid_owner>
  <displayname_owner>Name</displayname_owner>
  <permissions>1</permissions>
  <can_edit>1</can_edit>
  <can_delete>1</can_delete>
  <stime>1732182848</stime>
  <parent/>
  <expiration>2024-11-25 00:00:00</expiration>
  <token>rzJMHzxFPFYjYBf</token>
  <uid_file_owner>name</uid_file_owner>
  <note></note>
  <label></label>
  <displayname_file_owner>Name</displayname_file_owner>
  <path>/UNTERORDNER/Datei.zip</path>
  <item_type>file</item_type>
  <item_permissions>27</item_permissions>
  <mimetype>application/zip</mimetype>
  <has_preview></has_preview>
  <storage_id>home::name</storage_id>
  <storage>5</storage>
  <item_source>8625</item_source>
  <file_source>8625</file_source>
  <file_parent>690</file_parent>
  <file_target>/Datei.zip</file_target>
  <item_size>17606910</item_size>
  <item_mtime>1732182847</item_mtime>
  <share_with>3|$argon2id$v=19$m=65536,t=4,p=hagrfu45hr8zgfvhadsjhzur734q76tzghae94zhtgi</share_with>
  <share_with_displayname>(Geteilter Link)</share_with_displayname>
  <password>3|$argon2id$v=19$m=65536,t=4,p=hagrfu45hr8zgfvhadsjhzur734q76tzghae94zhtgi</password>
  <send_password_by_talk></send_password_by_talk>
  <url>https://domainname.de/nextcloud/index.php/s/mjkjvsfd8zgheajih</url>
  <mail_send>1</mail_send>
  <hide_download>0</hide_download>
  <attributes/>
 </data>
</ocs>

21.11.2024 10:54:08: Fehler beim Erstellen der Freigabe: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.  


Die generierte <url> funktioniert mit Downloadpasswort aus :

string ncpassword2 = "1234567890";   

Was nicht passiert ist, ist das Setzen des Tags sowie die Rückmeldung des Freigabelinks an meine APP.

Wie gesagt , die generierte URL wird ja zurück gemeldet und ist im log zu sehen und nutzbar.

Irgendeine Idee ?

Gruß
150940
Lösung 150940 21.11.2024 aktualisiert um 13:16:31 Uhr
Goto Top
Klar, hatte Tomaten auf den Augen ... Der Fehler liegt in der Umwandlung der Antwort des Servers, du versuchst die XML Antwort des Servers in ein JSON Object konvertieren was natürlich niemals klappen kann und dann eine Exception ausgelöst wird ... face-wink
dynamic shareResponseJson = JsonConvert.DeserializeObject(responseContent);

Doku lesen.
https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OC ...
Result: XML containing the share ID (int) of the newly created share

Also Antwort als statt als JSON als XMLDocument parsen und schon lüppt dat.
System.Text.XmlDocument xmldoc = new System.Text.XmlDocument();
xmldoc.LoadXml(resposeContent);
string shareurl = xmldoc.SelectSingleNode("/ocs/data/url").InnerText;  
Crashzero
Crashzero 21.11.2024 um 16:24:21 Uhr
Goto Top
Super, das klappt astrein.

Was ich allerdings leider nicht in der Doku finde ist wie ich ein Schlagwort auf die Datei lege .
                                        // Schlagwort "2Tage" auf die Datei setzen 
                                        string filePath = $"/{ncordnername}/{dateiname}";   

                                        // API-Endpunkt zum Hinzufügen eines Tags ? Ist das richtig hier ?
                                        string setTagUrl = $"{ocUrl}/ocs/v2.php/apps/files/api/v1/tags";  

                                        var tagRequestData = new FormUrlEncodedContent(new[]
                                        {
                                    new KeyValuePair<string, string>("path", filePath),  
                                    new KeyValuePair<string, string>("tag", "2Tage")  

Ist der API-Augruf hier richtig ?
Leider finde ich nix in der Doku dazu oder habs überlesen oder im falschen Abschnitt gesucht.

Gruß
150940
Lösung 150940 21.11.2024 aktualisiert um 16:49:45 Uhr
Goto Top
Ist der API-Augruf hier richtig ?
Nein.
Was ich allerdings leider nicht in der Doku finde ist wie ich ein Schlagwort auf die Datei lege.
Hatte ich doch oben schon ein PS-Beispiel verlinkt, einfach nachmachen und in C# umsetzen. Ist übrigens dein eigener Beitrag 🙃.

Die Doku dafür ist übrigens noch die gleiche wie für OwnCloud, denn Nextcloud ist ja auch nur ein Fork dessen. Diese funktioniert nach wie vor auch für Nextcloud...
Assign a Tag to a File

Good luck. 👋
Crashzero
Crashzero 21.11.2024 um 16:59:55 Uhr
Goto Top
So, jup funktioniert.

Ich danke dir.