OverFlowException beim Upload großer Dateien

  • VB.NET

Es gibt 32 Antworten in diesem Thema. Der letzte Beitrag () ist von Artentus.

    OverFlowException beim Upload großer Dateien

    Folgende FTP-Upload-Methode produziert bei folgender Datei:




    folgende Exception:


    in Zeile:

    VB.NET-Quellcode

    1. Dim bytes As Byte() = New Byte(CInt((fileinput.Length) - 1)) {}


    // Edit: Kriege das mit der Code-Formatierung hier im Forum nicht gerade gut hin..

    VB.NET-Quellcode

    1. Private Sub Upload(ByVal filename As String, ByVal remotepath As String)
    2. ftpclient.Host = sFtpHost : ftpclient.Credentials = credentials : ftpclient.EncryptionMode = FtpEncryptionMode.Explicit
    3. AddHandler ftpclient.ValidateCertificate, AddressOf SSLcertificateHandler
    4. Using ftpclient
    5. Using outputstream As Stream = ftpclient.OpenWrite(Chr(34) + remotepath + Chr(34))
    6. Dim fileinput As New FileStream(filename, FileMode.Open, FileAccess.Read)
    7. Try Dim bytes As Byte() = New Byte(CInt((fileinput.Length) - 1)) {}
    8. Dim numBytesToRead As Integer = CType(fileinput.Length, Integer)
    9. Dim numBytesRead As Integer = 0
    10. While (numBytesToRead > 0)
    11. Dim n As Integer = fileinput.Read(bytes, numBytesRead, numBytesToRead) If (n = 0) Then
    12. Exit While
    13. End If
    14. numBytesRead = (numBytesRead + n) : numBytesToRead = (numBytesToRead - n)
    15. End While
    16. numBytesToRead = bytes.Length outputstream.Write(bytes, 0, numBytesToRead)
    17. Finally
    18. fileinput.Close() : outputstream.Close()
    19. End Try End Using End Using
    20. End Sub


    Wie kann ich meinen Upload gegenüber sehr großen Dateien absichern? Mir ist natürlich klar, dass so große Dateien eher selten bis gar nicht per FTP übertragen werden übers Netz. Vorkommen könnte es aber trotzdem. Beispielsweise in einem Firmennetz intern (hier vorliegend) wäre es hilfreich wenn ich auch große Dateien hochladen kann.

    Gruß

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „vrtz“ () aus folgendem Grund: Schlechte Formatierung des Code Feldes

    So wie es aussieht hast du einen arithmetischen Überlauf bekommen. Wahrscheinlich weil Integer mit so großen Zahlen, das es ja in Bytes angegeben ist, nicht klar. Versuch es mal mit Long, dieser Datentyp hält mehr aus. Ich hatte das Problem auch erst und dann hab ich es mit Long hingekriegt.
    Problematisch ist aber das fileinput.read als Parameter umbedingt Integer haben möchte, weshalb ich die Longs dann wieder umformen müsste. Habe es so probiert mit Long:

    VB.NET-Quellcode

    1. Using outputstream As Stream = ftpclient.OpenWrite(Chr(34) + remotepath + Chr(34))
    2. Dim fileinput As New FileStream(filename, FileMode.Open, FileAccess.Read)
    3. Try Dim bytes As Byte() = New Byte(CInt((fileinput.Length) - 1)) {}
    4. Dim numBytesToRead As Long = CType(fileinput.Length, Integer)
    5. Dim numBytesRead As Long = 0
    6. While (numBytesToRead > 0)
    7. Dim n As Long = fileinput.Read(bytes, CInt(numBytesRead), CInt(numBytesToRead))
    8. If (n = 0) Then
    9. Exit While
    10. End If
    11. numBytesRead = (numBytesRead + n) : numBytesToRead = (numBytesToRead - n)
    12. End While
    13. numBytesToRead = bytes.Length
    14. outputstream.Write(bytes, 0, CInt(numBytesToRead))
    15. Finally
    16. fileinput.Close() : outputstream.Close()
    17. End Try End Using


    Übrigens wird mir bei der Exception als Tipp angezeigt das ich nicht durch 0 dividieren solle. Wo passiert das denn?
    Achso ja dann hast du irgendwo einen Wert der 0 ist und durch den versuchst du dann zu dividieren.
    Ich steige bei deinem Code sowieso nicht so ganz durch.

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Lädt eine Datei auf einen FTP-Server hoch.
    3. ''' </summary>
    4. ''' <returns></returns>
    5. ''' <remarks></remarks>
    6. Public Function UploadFile(ByVal URL As String, ByVal SourceFile As String, ByVal Username As String, ByVal Password As String) As Boolean
    7. URL = URL.TrimEnd(CChar("/")) & "/" & System.IO.Path.GetFileName(SourceFile)
    8. FTPRequest = CType(FtpWebRequest.Create(URL), FtpWebRequest)
    9. FTPRequest.Credentials = New NetworkCredential(Username, Password)
    10. FTPRequest.KeepAlive = True
    11. FTPRequest.UseBinary = True
    12. FTPRequest.Method = WebRequestMethods.Ftp.UploadFile
    13. Using FileStream As New System.IO.FileStream(SourceFile, System.IO.FileMode.Open, System.IO.FileAccess.Read), FTPStream As System.IO.Stream = FTPRequest.GetRequestStream
    14. RaiseEvent BeforeUpload(Me, New EventArgs)
    15. SpeedStopWatch.Start()
    16. Upload:Do
    17. If Paused = True Then GoTo Upload
    18. If UserCanceled = True Then : RaiseEvent UploadAborted(Me, New EventArgs) : Exit Do : End If
    19. If InternetGetConnectedState(0, 0) = False Then GoTo Upload
    20. BytesRead = FileStream.Read(Buffer, 0, 5121)
    21. _BytesUploaded += BytesRead
    22. BetwQuant += BytesRead
    23. If BytesRead = 0 Then
    24. Exit Do
    25. End If
    26. FTPStream.Write(Buffer, 0, CInt(BytesRead))
    27. _Percentage = Math.Round((_BytesUploaded / FileStream.Length) * 100)
    28. _TotalBytes = FileStream.Length
    29. If SpeedStopWatch.ElapsedMilliseconds >= 1000 Then '>Falls die Zeiteinheit voll ist (1 Sekunde), Geschwindigkeit berechnen
    30. SpeedStopWatch.Reset() 'Stoppuhr zurücksetzen
    31. _UploadSpeed = BetwQuant \ 1024 'Geschwindigkeit berechnen
    32. SpeedStopWatch.Start() 'Stoppuhr starten
    33. BetwQuant = 0 'Byte-Zähler zurücksetzen
    34. _RemainingTime = ((_TotalBytes - _BytesUploaded) \ 1024) \ _UploadSpeed
    35. End If
    36. RaiseEvent UploadProgressChanged(Me, New UploadProgressChangedEventArgs(_Percentage, _BytesUploaded, _TotalBytes, _UploadSpeed, _RemainingTime))
    37. Loop
    38. End Using
    39. SpeedStopWatch.Stop()
    40. RaiseEvent UploadFinished(Me, New EventArgs)
    41. End Function
    Das ist meine Funktion aus meiner Klasse. Die Deklarationen sind jetzt aber nicht dabei es sollte aber verständlich sein. Ich habe alle Variablen die was mit Zahlen zu tun haben als Long deklariert aus die Variable _Percentage die ist als Double deklariert
    Habe die Upload-Methode nach deinem Vorbild so umgebaut:

    VB.NET-Quellcode

    1. Dim bytesUploaded As Long
    2. Dim betwQuant As Long
    3. Using FileStream As New System.IO.FileStream(filename, FileMode.Open, FileAccess.Read), outputstream As Stream = ftpclient.OpenWrite(Chr(34) + remotepath + Chr(34))
    4. Do
    5. Dim buffer As Byte() = New Byte((CInt(FileStream.Length) - 1)) {}
    6. Dim bytesread As Long = FileStream.Read(buffer, 0, 5121)
    7. bytesUploaded += bytesread
    8. betwQuant += bytesread
    9. If bytesread = 0 Then
    10. Exit Do
    11. End If
    12. outputstream.Write(buffer, 0, CInt(bytesread))
    13. Loop
    14. End Using



    Warum habe ich denn mit deiner Variante (also meinem Nachbau, s.o.) einen Upload von unter 1 MB/s auf meinen localhost FileZilla-Server und mit meiner Variante 15-20 Mb/s ?

    Mit der Variante von diesem Post kommt übrigens dieselbe OverflowException wie mit meiner alten Variante.
    Das weiß ich halt nicht so ganz genau. Also meine Berechnung wird wohl stimmen, da ich die gleiche Berechnung auch in meiner Download-Klasse verwende und das Ergebnis dann immer mit dem übereinstimmt, was mein Browser anzeigt.
    Ich nutze nur die .NET Framework internen FTP-Hilfsmittel.
    Was für eine Exception? Dann probier mal meine Funktion aus, ohne sie zu verändern. Hier ist mal die ganze Klasse wegen Deklarationen

    VB.NET-Quellcode

    1. Public Class Upload
    2. Private Buffer(5120) As Byte
    3. Private BytesRead As Long = 0
    4. Private _BytesUploaded As Long = 0
    5. Private _Percentage As Double = 0
    6. Private _TotalBytes As Long = 0
    7. Private BetwQuant As Long = 0
    8. Private _UploadSpeed As Long = 0
    9. Private _RemainingTime As Long = 0
    10. Private FTPRequest As FtpWebRequest
    11. Private SpeedStopWatch As New Stopwatch
    12. ''' <summary>
    13. ''' Lädt eine Datei auf einen FTP-Server hoch.
    14. ''' </summary>
    15. ''' <returns></returns>
    16. ''' <remarks></remarks>
    17. Public Function UploadFile(ByVal URL As String, ByVal SourceFile As String, ByVal Username As String, ByVal Password As String) As Boolean
    18. URL = URL.TrimEnd(CChar("/")) & "/" & System.IO.Path.GetFileName(SourceFile)
    19. FTPRequest = CType(FtpWebRequest.Create(URL), FtpWebRequest)
    20. FTPRequest.Credentials = New NetworkCredential(Username, Password)
    21. FTPRequest.KeepAlive = True
    22. FTPRequest.UseBinary = True
    23. FTPRequest.Method = WebRequestMethods.Ftp.UploadFile
    24. Using FileStream As New System.IO.FileStream(SourceFile, System.IO.FileMode.Open, System.IO.FileAccess.Read), FTPStream As System.IO.Stream = FTPRequest.GetRequestStream
    25. RaiseEvent BeforeUpload(Me, New EventArgs)
    26. SpeedStopWatch.Start()
    27. Upload: Do
    28. BytesRead = FileStream.Read(Buffer, 0, 5121)
    29. _BytesUploaded += BytesRead
    30. BetwQuant += BytesRead
    31. If BytesRead = 0 Then
    32. Exit Do
    33. End If
    34. FTPStream.Write(Buffer, 0, CInt(BytesRead))
    35. _Percentage = Math.Round((_BytesUploaded / FileStream.Length) * 100)
    36. _TotalBytes = FileStream.Length
    37. If SpeedStopWatch.ElapsedMilliseconds >= 1000 Then '>Falls die Zeiteinheit voll ist (1 Sekunde), Geschwindigkeit berechnen
    38. SpeedStopWatch.Reset() 'Stoppuhr zurücksetzen
    39. _UploadSpeed = BetwQuant \ 1024 'Geschwindigkeit berechnen
    40. SpeedStopWatch.Start() 'Stoppuhr starten
    41. BetwQuant = 0 'Byte-Zähler zurücksetzen
    42. _RemainingTime = ((_TotalBytes - _BytesUploaded) \ 1024) \ _UploadSpeed
    43. End If
    44. Loop
    45. End Using
    46. SpeedStopWatch.Stop()
    47. End Function
    48. End Class
    Lies nicht alles auf einmal aus...
    uneingeschränkt zustimm!

    Weil große Datenbestände gepuffert verschieben, das ist die grundlegendste Grundidee des Stream-Konzeptes - gugget auch Stream-Konzepte

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

    Artentus schrieb:


    Lies nicht alles auf einmal aus, sondern immer nur Stück für Stück. Die Exception kommt wohl, weil du zu viel in den Arbeitsspeicher lädst.

    Und nur mal so: Warum willst du StarCraft2 auf deinen FTP hochladen?
    Ich suchte eine einzelne große Datei aus reinen Testzwecken. Das war die erste die ausreichend groß war :) Da es sich um einen lokalen FileZilla-Server handelt, werden die Test-Dateien momentan sowieso nur auf meine zweite Partition geschoben. Ich habe nicht vor in der Praxis eine solche Datei zu verbreiten ;)

    Kann ich denn nicht größere Blöcke nehmen als die 5121 Bytes? Die Upload-Geschwindigkeit scheint ja sehr darunter zu leiden.