Zugriff auf Datei nach FileStream.Close verweigert

  • VB.NET

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von SpaceyX.

    Zugriff auf Datei nach FileStream.Close verweigert

    Guten Tag

    Ich schreibe gerade meine eigene Klasse zum Downloaden von Dateien. In diese Klasse habe ich eine Funktion eingebaut, mit welcher man den Download fortsetzen kann, wenn er unterbrochen wird.
    Aber ich hab damit ein Problem. Wenn ich vorher in meiner AbortDownload-Methode den Download abbreche, schließe ich auch mit FileStream.Close den Stream. Wenn ich zum Fortsetzen einen neuen FileStream auf die Datei zugreifen lassen will, kommt folgende Fehlermeldung.

    Quellcode

    1. Auf eine geschlossene Datei kann nicht zugegriffen werden.


    Wie kann ich aber trotzdem auf die Datei zugreifen?

    Vielen Dank im Voraus.

    Breadsoft
    Is klar. Wenn der Tankdeckel drauf ist, kommt kein Benzin in den Tank.
    Entweder Du lässt den Stream offen bis der Vorgang beendet ist oder Du disposest und öffnest ihn wieder (Achtung: File-Append), nimm dazu ein Using.
    Ansonsten schick mal den Code vorbei.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hey,

    ROD hat Dir doch schon den entscheidenden Hinweis gegeben. Du kannst beim Abbrechen den FileStream ruhig schliessen. Wird der Download wieder aufgenommen, dann übergibst Du beim Konstruktor des FileStreams einfach FileMode.Append.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

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

    Breadsoft schrieb:

    Aber wie soll ich den Download dann abbrechen können,
    Das Problem dürfte eher darin bestehen, das Download dort fortzusetzen, wo es unterbrochen wurde.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hey,

    ich hab Dir mal was getippt, was eine Wiederaufnahme des Downloads erlaubt. Habs nicht wirklich durchgetestet und wahrscheinlich ziemlich fehlerbehaftet. Soll Dir aber auch nur ein Anhaltspunkt sein, wie man es machen kann.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class FileDownloader
    2. Public Property FileUri As Uri
    3. Private _totalReceived As Long
    4. Private _response As Net.HttpWebResponse = Nothing
    5. Private _interrupted As Boolean = False
    6. Private _fileStream As IO.FileStream = Nothing
    7. Private _asyncOp As System.ComponentModel.AsyncOperation
    8. Private _responseStream As IO.Stream = Nothing
    9. Private _fileName As String = ""
    10. Private _canceled As Boolean = False
    11. Public Event DownloadProgressChanged(ByVal sender As FileDownloader, ByVal percentage As Integer)
    12. Public Event DownloadCompleted(ByVal sender As FileDownloader, ByVal file As IO.FileInfo)
    13. Public Event DownloadInterrupted(ByVal sender As FileDownloader)
    14. Public Sub New(ByVal uri As Uri)
    15. _response = GetResponse(uri)
    16. If IsNothing(_response) Then
    17. Throw New FileNotExistsException()
    18. End If
    19. Me.FileUri = uri
    20. _responseStream = _response.GetResponseStream()
    21. _asyncOp = System.ComponentModel.AsyncOperationManager.CreateOperation(Nothing)
    22. _fileName = _response.ResponseUri.AbsolutePath.Replace("/", "")
    23. End Sub
    24. Private Sub DoDownload()
    25. Dim buffer(1000000) As Byte
    26. Dim recLen As Integer = 0
    27. Dim progress As Integer = 0
    28. If IsNothing(_responseStream) Then
    29. _response = GetResponse(Me.FileUri)
    30. _responseStream = _response.GetResponseStream()
    31. End If
    32. If IsNothing(_fileStream) Then
    33. _fileStream = New IO.FileStream("tmp.file", IO.FileMode.OpenOrCreate, IO.FileAccess.ReadWrite)
    34. Else
    35. _fileStream = New IO.FileStream("tmp.file", IO.FileMode.Append, IO.FileAccess.Write)
    36. End If
    37. Do
    38. If _interrupted Then
    39. _fileStream.Close()
    40. _asyncOp.Post(New Threading.SendOrPostCallback(AddressOf OnDownloadInterrupted), Nothing)
    41. Exit Do
    42. End If
    43. If _canceled Then
    44. _fileStream.Close()
    45. _responseStream.Close()
    46. _response = Nothing
    47. _responseStream = Nothing
    48. _fileStream = Nothing
    49. _totalReceived = 0
    50. End If
    51. recLen = _responseStream.Read(buffer, 0, buffer.Length)
    52. _totalReceived += recLen
    53. progress = Convert.ToInt32((_totalReceived * 100) / _response.ContentLength)
    54. _asyncOp.Post(New Threading.SendOrPostCallback(AddressOf OnProgressChanged), DirectCast(progress, Object))
    55. If recLen = 0 Then
    56. _responseStream.Close()
    57. _fileStream.Close()
    58. _responseStream.Close()
    59. _fileStream = Nothing
    60. _response = Nothing
    61. _responseStream = Nothing
    62. _totalReceived = 0
    63. IO.File.Move("tmp.file", _fileName)
    64. _asyncOp.Post(New Threading.SendOrPostCallback(AddressOf OnDownloadComplete), DirectCast(New IO.FileInfo(_fileName), Object))
    65. Exit Do
    66. End If
    67. _fileStream.Write(buffer, 0, recLen)
    68. Loop
    69. End Sub
    70. Public Sub BeginDownload()
    71. If _interrupted Then
    72. Exit Sub
    73. End If
    74. If _canceled Then
    75. _canceled = False
    76. End If
    77. Dim a As Action = AddressOf DoDownload
    78. a.BeginInvoke(Nothing, Nothing)
    79. End Sub
    80. Public Sub InterruptDownload()
    81. _interrupted = True
    82. End Sub
    83. Public Sub CancelDownload()
    84. _canceled = True
    85. End Sub
    86. Public Sub ResumeDownload()
    87. _interrupted = False
    88. Dim a As Action = AddressOf DoDownload
    89. a.BeginInvoke(Nothing, Nothing)
    90. End Sub
    91. Private Function GetResponse(ByVal uri As Uri) As Net.HttpWebResponse
    92. Dim hReq As Net.HttpWebRequest = Nothing
    93. Dim hRes As Net.HttpWebResponse = Nothing
    94. hReq = DirectCast(Net.HttpWebRequest.Create(uri), Net.HttpWebRequest)
    95. hReq.Proxy = Nothing
    96. Try
    97. hRes = DirectCast(hReq.GetResponse(), Net.HttpWebResponse)
    98. If Not hRes.StatusCode = Net.HttpStatusCode.OK Then
    99. Return Nothing
    100. End If
    101. Catch ex As Exception
    102. Return Nothing
    103. End Try
    104. Return hRes
    105. End Function
    106. Private Sub OnDownloadComplete(ByVal o As Object)
    107. Dim fi As IO.FileInfo = DirectCast(o, IO.FileInfo)
    108. RaiseEvent DownloadCompleted(Me, fi)
    109. End Sub
    110. Private Sub OnDownloadInterrupted(ByVal o As Object)
    111. RaiseEvent DownloadInterrupted(Me)
    112. End Sub
    113. Private Sub OnProgressChanged(ByVal o As Object)
    114. Dim progress As Integer = DirectCast(o, Integer)
    115. RaiseEvent DownloadProgressChanged(Me, progress)
    116. End Sub
    117. End Class
    118. Public Class FileNotExistsException : Inherits Exception
    119. Public Sub New()
    120. MyBase.New("This file does not exist")
    121. End Sub
    122. End Class

    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Könntest du mir erklären wie ich das anders lösen könnte weil mir bringt das ja nichts einfach code zu kopieren weil ich dabei nichts lerne.

    Wenn ich den Stream schließe, kommt die Fehlermeldung:"Auf eine geschlossene Datei kann nicht zugegriffen werden."
    Wenn ich den Stream aber nicht schließe, kommt die Fehlermeldung:"Auf die Datei ... kann nicht zugegriffen werden, weil ein anderer Prozess darauf zugreift.
    Du sollst den Code doch auch nicht kopieren, sondern vielleicht als Anhaltspunkt nehmen.

    Du kannst den FileStream jederzeit schliessen und jederzeit wieder öffnen. Und zwar mit dem .Append Argument.

    Genau hier wird das gemacht:

    VB.NET-Quellcode

    1. If IsNothing(_fileStream) Then
    2. _fileStream = New IO.FileStream("tmp.file", IO.FileMode.OpenOrCreate, IO.FileAccess.ReadWrite)
    3. Else
    4. _fileStream = New IO.FileStream("tmp.file", IO.FileMode.Append, IO.FileAccess.Write)
    5. End If
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Du stellst immer wieder die selben Fragen. Schau in den Code, den ich extra für Dich getippt habe, da steht alles drin. Wie man ihn pausiert, wie man ihn wieder aufnimmt.

    EDIT: Im Dateianhang findest Du das Projekt zum selber Probieren!

    EDIT2: Evtl. ists auch etwas einfacher, das Vorhaben, einen Download anzuhalten und wieder fortzusetzen, einfach auszulassen. Dann kannst Dich dem WebClient widmen. Da ist vieles einfacher.
    Dateien
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

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