"Dateiablage" auf Storage anstatt Datenbank

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 33 Antworten in diesem Thema. Der letzte Beitrag () ist von BlueLagoonX.

    "Dateiablage" auf Storage anstatt Datenbank

    Hallo zusammen.

    In meinem großen Programm werden u.A. Dokumente, Bilder und Scans aktuell auf den Netzlaufwerken der verschiedenen Standorte gespeichert und können
    dann wiederum über das Programm geöffnet und eingesehen werden.

    Jetzt ist die Überlegung (eigentlich keine Überlegung sondern ein Muss) die Dateien an einem Zentralen Ort abzulegen (Ordnerstruktur ist im Programm dann vorgegeben).
    Mir stehen nun folgende Möglichkeiten zur Auswahl:
    • OneDrive
    • SharePoint
    • Azure Storage

    Leider komm ich mit meinem Halbwissen mit keinem der 3 Arten klar, denn hier lässt sich ja nichts speichern/öffnen/Ordner anlegen wie z.b. mit einem normalen lokalen oder UNC-Pfad.
    OneDrive und SharePoint scheinen ähnlich zu arbeiten, Azure-Storage ist für mich konfus, denn ich hätte da gerne zumindest einen passwortgeschützten Zugang.

    Was würdet ihr empfehlen und wie stelle ich es an, dass ich die URL's (von OneDrive oder SharePoint) in "normal benutzbare" Pfade umwandle?
    Ich möchte die Dateien in der Programm-Zugehörigen Datenbank nicht wirklich hinterlegen, das würde wohl sehr schnell sehr groß werden das Ganze.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Bei Azure kann man ja kostenlos testen für ein Jahr oder sowas.
    Ich komm mit dem aber nicht klar. Azure ist absolutes Neuland für mich.. Azure Files ist eingerichtet, ich komm auch über den Azure Storage Explorer dran - aber wie binde ich das ganze ein
    und hab ich da ne Möglichkeit User und PW oder zumindest ein Zugriffspasswort anzulegen?

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Bei OneDrive musst Su daran denken, das der Pfad für jeden User anderes ist. Du kannst aber den lokalen Pfad wie einen normalen Ordner verwenden.

    Ich würde das wahrscheinlich das Speichern über OneDrive machen und in der Datenbank den Pfad zum Sharepoint hinterlegen. OneDrive und Sharepoint legen die Daten an der gleichen Stelle ab, sie werden nur unterschieddlich adressiert.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    @Fakiz @ISliceUrPanties
    Hab mir den Link angeschaut, ich blick' da aber überhaupt nicht durch.
    Was ich in meiner Anwendung brauch:

    - gescannte Dokumente speichern (pdfdocument.save aus pdfsharp)
    - Dateien kopieren und verschieben (File.Copy und File.Move)
    - Dateien anzeigen (am liebsten direkt vom Storage ohne vorher auf ein lokales Laufwerk zu kopieren)

    Bekommt man das mit SharePoint oder Azure File Storage hin? Wenn nicht, was gibt's für andere Möglichkeiten?
    Der Storage muss von überall abgreifbar sein...
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    ISliceUrPanties schrieb:

    Was genau macht dir Schwierigkeiten?

    So ziemlich alles. Ist mir völlig neu und fremd nicht so zu arbeiten, wie ich es lokal kenne.
    Also Account, Abo etc. ist eingerichtet -> Das muss ich später recht Easy ändern können auf Azure von der Firma.
    Storage ist eingerichtet, ebenso die Freigabe - und auch SAS konnte ich schon einrichten - leuchtet mir soweit auch ein.

    Was mir Schwierigkeiten bereitet ist das Arbeiten auf dem Storage von vb.net aus (Codeseitig).
    Soweit ich das verstanden hab:

    -muss ich mich jedes mal "anmelden" -> mit dem ConnectionString, der mir aus dem SAS generiert wird?
    -Dateiupload über FIleStream -> heißt verschieben ist nicht, sondern nach erfolgreichem Upload lokal dann löschen?
    -kann ich vorher prüfen (wie lokal mit If Not Directory.Exists Then..) ob ein Ordner auf dem Share existiert? Oder jedesmal mit directory.Create() laufen lassen und er macht den Rest selbst?
    -Dateien anzeigen: Wenn ich das richtig lese läuft das ja auch über nen FileStream. Muss ich den zwingend auf Platte speichern oder kann ich mir die Datei aus dem Stream direkt öffnen?

    Jo das wären erstmal die offenen Fragen. Denke hier fehlt mir generell das Grundverständnis für die ganze Sache

    Edit: Hab mal angefangen das in VB.net einzubauen am Beispiel "Create a share and upload a file". Das Create a Share kann ich weglassen, File Uploaden muss ja.
    Ich hab allerdings Probleme mit der Übersetzung nach VB:

    C#-Quellcode

    1. using (FileStream stream = File.OpenRead(localFilePath))
    2. {
    3. file.Create(stream.Length);
    4. file.UploadRange(
    5. new HttpRange(0, stream.Length),
    6. stream);
    7. }
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „tragl“ ()

    tragl schrieb:

    -muss ich mich jedes mal "anmelden" -> mit dem ConnectionString, der mir aus dem SAS generiert wird?

    Ja, ich gehe davon aus. Evtl. kannst du dir eine Art Session erzeugen, damit du dich nicht immer wieder anmelden musst.

    tragl schrieb:

    -Dateiupload über FIleStream -> heißt verschieben ist nicht, sondern nach erfolgreichem Upload lokal dann löschen?

    Ja, sieht wohl so aus.

    tragl schrieb:

    -kann ich vorher prüfen (wie lokal mit If Not Directory.Exists Then..) ob ein Ordner auf dem Share existiert? Oder jedesmal mit directory.Create() laufen lassen und er macht den Rest selbst?

    Ja, wird auch in den Beispielen bei MS gezeigt.

    tragl schrieb:

    -Dateien anzeigen: Wenn ich das richtig lese läuft das ja auch über nen FileStream. Muss ich den zwingend auf Platte speichern oder kann ich mir die Datei aus dem Stream direkt öffnen?

    Ja, geht auch. Schau mal hier learn.microsoft.com/en-us/dotn….shares?view=azure-dotnet. Speziell die Klassen ShareFileClient und ShareDirectoryClient. Die haben Methoden zum Öffnen und anzeigen.
    @ISliceUrPanties
    Danke für die Info's - dann hab ich das "Gerüst" ja soweit verstanden. Könntest du mir bei der Übersetzung noch behilflich sein?
    Der CodeConverter C# -> VB spuckt leider einen Error aus und ich bin mit Streams und dessen Handhabung absolut noch nicht vertraut.

    Spoiler anzeigen

    Error converting code

    Error message:

    CONVERSION ERROR: Conversion for IncompleteMember not implemented, please report this issue in 'share.Create' at character 869

    at ICSharpCode.CodeConverter.VB.NodesVisitor.DefaultVisit(SyntaxNode node)

    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitIncompleteMember(IncompleteMemberSyntax node)

    at Microsoft.CodeAnalysis.CSharp.Syntax.IncompleteMemberSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)

    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)

    at ICSharpCode.CodeConverter.VB.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)

    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitIncompleteMember(IncompleteMemberSyntax node)

    at Microsoft.CodeAnalysis.CSharp.Syntax.IncompleteMemberSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)

    at ICSharpCode.CodeConverter.VB.NodesVisitor.<VisitClassDeclaration>b__23_0(MemberDeclarationSyntax m)

    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()

    at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)

    at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

    at ICSharpCode.CodeConverter.VB.NodesVisitor.VisitClassDeclaration(ClassDeclarationSyntax node)

    at Microsoft.CodeAnalysis.CSharp.Syntax.ClassDeclarationSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)

    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)

    at ICSharpCode.CodeConverter.VB.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)

    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitClassDeclaration(ClassDeclarationSyntax node)

    at Microsoft.CodeAnalysis.CSharp.Syntax.ClassDeclarationSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)

    at ICSharpCode.CodeConverter.VB.NodesVisitor.<VisitCompilationUnit>b__15_1(MemberDeclarationSyntax m)

    at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()

    at Microsoft.CodeAnalysis.SyntaxList`1.CreateNode(IEnumerable`1 nodes)

    at Microsoft.CodeAnalysis.SyntaxList`1..ctor(IEnumerable`1 nodes)

    at Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.List[TNode](IEnumerable`1 nodes)

    at ICSharpCode.CodeConverter.VB.NodesVisitor.VisitCompilationUnit(CompilationUnitSyntax node)

    at Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)

    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)

    at ICSharpCode.CodeConverter.VB.CommentConvertingNodesVisitor.DefaultVisit(SyntaxNode node)

    at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.VisitCompilationUnit(CompilationUnitSyntax node)

    at Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)

    at ICSharpCode.CodeConverter.VB.CSharpConverter.ConvertCompilationTree(CSharpCompilation compilation, CSharpSyntaxTree tree)

    at ICSharpCode.CodeConverter.VB.CSToVBConversion.SingleFirstPass(Compilation sourceCompilation, SyntaxTree tree)

    at ICSharpCode.CodeConverter.Shared.ProjectConversion.SingleFirstPass(SyntaxTree tree, String treeFilePath)

    at ICSharpCode.CodeConverter.Shared.ProjectConversion.FirstPass()



    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    tragl schrieb:

    Der CodeConverter C# -> VB spuckt leider einen Error

    icsharpcode.github.io/CodeConverter/ der macht keinen Fehler. Wobei der Code nicht sonderlich komplex ist und das auch hätte zu Fuß klappen müssen.

    VB.NET-Quellcode

    1. ​Using stream = File.OpenRead(localFilePath)
    2. file.Create(stream.Length)
    3. file.UploadRange(New HttpRange(0, stream.Length), stream)
    4. End Using

    ErfinderDesRades schrieb:

    Das sollte dir jeder Online-Converter fehlerfrei rüberbringen können

    eben nicht

    ISliceUrPanties schrieb:

    der macht keinen Fehler.

    danke.

    Ich hab bisher den Converter von converter.telerik.com/ genutzt, der kommt damit nicht klar. Den anderen hab ich mir mal gebookmarked :)
    Ich tüftel' dann mal rum.
    EDIT: Der Upload und Verzeichnisprüfung etc. hat schonmal sauber funktioniert. Dann bekomm' ich den Rest nu sicher auch hin ;)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    @ErfinderDesRades: wird wohl der Fehler gewesen sein - ist mir nicht aufgefallen.

    Ich steh' noch vor einem kleinen Rätsel. Datei runterladen vom Storage und Öffnen klappt nun - scheint nicht ohne temp-File zu gehen.
    Nu möchte ich aber gerne nach dem Schließen der Datei, dass die temp-datei auch wieder gelöscht wird, damit sich die PC's nicht zu müllen.

    Allerdings reagiert der EventHandler nicht drauf... wo hab ich denn den Denkfehler?
    Also in Zeile 14 wird die Datei geöffnet, Zeile 18 sollte drauf reagieren wenn ich das wieder schließe (pdf, photo-vorschau oder was auch immer).

    VB.NET-Quellcode

    1. Private _fi As FileInfo
    2. Private WithEvents _proc As Process
    3. Public Sub OpenFileFromAzureStorage(Filename As String, ShareDirectory As String)
    4. Dim shareClient = New Files.Shares.ShareClient(App.AzureConnectionString, App.AzureShareName)
    5. Dim shareDirClient = shareClient.GetDirectoryClient(ShareDirectory)
    6. Dim shareFileClient = shareDirClient.GetFileClient(Filename)
    7. Dim shareFileDownloadInfo As Files.Shares.Models.ShareFileDownloadInfo = shareFileClient.Download
    8. _fi = New FileInfo($"{App.AzureLocalTempFolder}\{Filename}")
    9. If File.Exists(_fi.FullName) Then File.Delete(_fi.FullName)
    10. Using stream = File.OpenWrite($"{App.AzureLocalTempFolder}\{Filename}")
    11. shareFileDownloadInfo.Content.CopyTo(stream)
    12. End Using
    13. _proc = Process.Start(_fi.FullName)
    14. End Sub
    15. Private Sub ProcessExited(sender As Object, e As EventArgs) Handles _proc.Exited
    16. If _fi IsNot Nothing Then File.Delete(_fi.FullName)
    17. End Sub


    Edit: Auf das Exiten des Prozesses möchte ich nicht warten - gibt's ja auch mit .WaitForExit
    Macht es ggf. Sinn diese Prozesse in eine Liste zu schmeißen und beim Beenden des Programmes einmal aufzuräumen?
    Ggf. bestehende Prozesse zu killen und im Anschluss die Temp-Files löschen? Oder wie würdet ihr das Ganze angehen?
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „tragl“ ()

    Da fehlt m.E. ein _proc.EnableRaisingEvents = True
    Ansonsten wird einfach das Event nicht gefeuert und der EventHandler nicht aufgerufen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    Ansonsten wird einfach das Event nicht gefeuert


    Jo, stellt sich mir die Frage, warum. _proc.EnableRaisingEvents = True hab ich eingebaut, sogar mal nach MIcrosoft-Manier mit Using-Block und Addhandler.
    In meinem Test handelt es sich um eine .png-Datei vom Azure-Storage. Die wird mit dem Windows-Foto-Gedöns geöffnet - erkennt er den Process dann irgendwie nicht?


    VB.NET-Quellcode

    1. Private _fi As FileInfo
    2. Private WithEvents _proc As Process
    3. ''' <summary>Lädt eine Datei vom AzureStorage in eine temporäre lokale Datei und öffnet diese</summary>
    4. ''' <param name="Filename">der Dateiname inkl. Endung</param>
    5. ''' <param name="ShareDirectory">das Verzeichnis, indem sich die Datei befinden soll</param>
    6. Public Sub OpenFileFromAzureStorage(Filename As String, ShareDirectory As String)
    7. 'TODO: temporäre Datei nach Schließen wieder löschen
    8. Dim shareClient = New Files.Shares.ShareClient(App.AzureConnectionString, App.AzureShareName)
    9. Dim shareDirClient = shareClient.GetDirectoryClient(ShareDirectory)
    10. Dim shareFileClient = shareDirClient.GetFileClient(Filename)
    11. If shareFileClient.Exists Then
    12. Dim shareFileDownloadInfo As Files.Shares.Models.ShareFileDownloadInfo = shareFileClient.Download
    13. _fi = New FileInfo($"{App.AzureLocalTempFolder}\{Filename}")
    14. If File.Exists(_fi.FullName) Then File.Delete(_fi.FullName)
    15. Using stream = File.OpenWrite($"{App.AzureLocalTempFolder}\{Filename}")
    16. shareFileDownloadInfo.Content.CopyTo(stream)
    17. End Using
    18. Using _proc = New Process
    19. Try
    20. Dim procStartInfo As New ProcessStartInfo
    21. With procStartInfo
    22. .ErrorDialog = True
    23. .UseShellExecute = True
    24. .FileName = _fi.FullName
    25. End With
    26. _proc.StartInfo = procStartInfo
    27. _proc.EnableRaisingEvents = True
    28. AddHandler _proc.Exited, AddressOf _proc_Exited
    29. _proc.Start()
    30. Catch ex As Exception
    31. msgError(ex.Message)
    32. End Try
    33. End Using
    34. Else
    35. msgError($"Die angeforderte Datei {ShareDirectory}\{Filename} konnte auf dem Server nicht gefunden werden!")
    36. Return
    37. End If
    38. End Sub
    39. Private Sub ProcessExited(sender As Object, e As EventArgs)
    40. If _fi IsNot Nothing Then File.Delete(_fi.FullName)
    41. End Sub
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Langsam. Bau erstmal in ner TestApp das ProcExited mit nem einfachen Prozess nach, ohne Azure.
    AddHandler _proc.Exited, AddressOf _proc_Exited + Private Sub ProcessExited(sender As Object, e As EventArgs) Da besteht ja auch gar keine Verbindung. Wo ist die zugewiesene _proc_Exited-Sub?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    Wo ist die zugewiesene _proc_Exited-Sub?


    Sorry, war ein Fehler zwischen Bereinigen und hier rein kopieren. Es heißt korrekt AddHandler _proc.Exited, AddressOf ProcessExited und wurde auch so getestet.
    Außerdem hab ich getestet ohne AddHandler, dafür bei der Sub direkt mit "Handles _proc.Exited" zu arbeiten - geht auch nicht.

    FÜr mich ist das ein einfacher Prozess: -> Bilddatei öffnen und in der windows-foto-app oder wo auch immer anzeigen.
    Wenn ich das dann schließe hätte ich erwartet, dass der Handler anspringt. Mit Azure hat der Prozess ja nix zu tun - das wird ja vorher schon alles abgefrühstückt ;)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: