Tipp-Upload: VB.NET 0277: asynchroner HTTP - / FTP - Download
von Spatzenkanonier
Über den Tipp
Dieser Tippvorschlag ist noch unbewertet.
Der Vorschlag ist in den folgenden Kategorien zu finden:
- Internet und Netzwerke
Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
HTTP ,FTP , Download,thread,asynchron
Der Vorschlag wurde erstellt am: 10.06.2008 23:53.
Die letzte Aktualisierung erfolgte am 24.05.2009 10:51.
Beschreibung
Download von WebSites (per HTTP) und Files (per FTP)
sehr einfaches Threading
Schwierigkeitsgrad |
Verwendete API-Aufrufe: |
Download: |
' Dieser Source stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' ' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird. ' In den Zip-Dateien ist er jedoch zu finden. ' ----------- Anfang Projektgruppe WebDownload.sln ----------- ' ---------- Anfang Projektdatei WebDownload.vbproj ---------- ' --------------- Anfang Datei CrossThreadX.vb --------------- ' IDE-Voreinstellungen: ' Option Strict On ' Option Explicit On ' Option Infer On ' Projekt-Voreinstellungen ' Imports System ' Imports System.Windows.Forms ' Imports System.Collections.Generic ' Imports Microsoft.VisualBasic.ControlChars Imports System.Runtime.CompilerServices Namespace System.Windows.Forms ''' <summary> ''' Stellt Methoden bereit, mit denen ein beliebiger Methoden-Aufruf mit bis zu 3 Argumenten ''' in einen Nebenthread verlegt werden kann, bzw. aus einem Nebenthread in den Hauptthread ''' </summary> Public Module CrossThreadX <Extension()> _ Public Sub RunAsync(Of T1, T2, T3)( _ ByVal Action As Action(Of T1, T2, T3), _ ByVal Arg1 As T1, ByVal Arg2 As T2, ByVal Arg3 As T3) ' Aufruf von Action.EndInvoke() gewährleisten, indem er als Callback-Argument ' mitgegeben wird Action.BeginInvoke(Arg1, Arg2, Arg3, AddressOf Action.EndInvoke, Nothing) End Sub <Extension()> _ Public Sub RunAsync(Of T1, T2)( _ ByVal Action As Action(Of T1, T2), ByVal Arg1 As T1, ByVal Arg2 As T2) Action.BeginInvoke(Arg1, Arg2, AddressOf Action.EndInvoke, Nothing) End Sub <Extension()> _ Public Sub RunAsync(Of T1)(ByVal Action As Action(Of T1), ByVal Arg1 As T1) Action.BeginInvoke(Arg1, AddressOf Action.EndInvoke, Nothing) End Sub <Extension()> _ Public Sub RunAsync(ByVal Action As Action) Action.BeginInvoke(AddressOf Action.EndInvoke, Nothing) End Sub Private Function GuiCrossInvoke( _ ByVal Action As [Delegate], ByVal ParamArray Args() As Object) As Boolean If Application.OpenForms.Count = 0 Then ' wenn kein Form mehr da ist, so tun, als ob das Invoking ausgeführt wäre Return True End If If Application.OpenForms(0).InvokeRequired Then Application.OpenForms(0).BeginInvoke(Action, Args) Return True End If End Function <Extension()> _ Public Sub RunGui(Of T1, T2, T3)( _ ByVal Action As Action(Of T1, T2, T3), _ ByVal Arg1 As T1, ByVal Arg2 As T2, ByVal Arg3 As T3) If Not GuiCrossInvoke(Action, Arg1, Arg2, Arg3) Then Action(Arg1, Arg2, Arg3) End Sub <Extension()> _ Public Sub RunGui(Of T1, T2)( _ ByVal Action As Action(Of T1, T2), ByVal Arg1 As T1, ByVal Arg2 As T2) If Not GuiCrossInvoke(Action, Arg1, Arg2) Then Action(Arg1, Arg2) End Sub <Extension()> _ Public Sub RunGui(Of T1)(ByVal Action As Action(Of T1), ByVal Arg1 As T1) If Not GuiCrossInvoke(Action, Arg1) Then Action(Arg1) End Sub <Extension()> _ Public Sub RunGui(ByVal Action As Action) If Not GuiCrossInvoke(Action) Then Action() End Sub <Extension()> _ Public Sub RunGui(ByVal Action As Action(Of String), ByVal ParamArray args() As Object) Action.RunGui(String.Concat(args)) End Sub <Extension()> Public Function CreateAsync(Of T1, T2)(ByVal Action As Action(Of T1, _ T2)) As Action(Of T1, T2) Return AddressOf Action.RunAsync End Function End Module End Namespace ' ---------------- Ende Datei CrossThreadX.vb ---------------- ' -------------- Anfang Datei frmWebDownload.vb -------------- Imports System.Net Imports System.IO Imports System.Threading Public Class frmWebDownload Private _DownloadDir As New DirectoryInfo("Downloads") ' Private _Download As Action(Of WebRequest, String) = AddressOf Download Private _Download As Action(Of WebRequest, String) = CreateAsync(Of WebRequest, String)( _ AddressOf Download) Private _DisplayMessage As Action(Of String) Private Sub frmWebDownload_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load _DisplayMessage = AddressOf RichTextBox1.AppendText With _DownloadDir If .Exists Then .Delete(True) .Create() End With ' WebSites für HTTP-Download Me.cmbHTTP.DataSource = New String() { _ "http://foren.activevb.de/cgi-bin/foren/list.pl?forum=6", _ "http://www.activevb.de/cgi-bin/upload/upload.pl"} ' Downloads für FTP-Download Me.cmbFTP.DataSource = New String() { _ "http://www.activevb.de/tipps/vbnetdownloads/tipp0018.zip", _ "http://www.apiviewer.de/downloadsstore/apv2004_v310.exe"} End Sub Private Function InsertID(ByVal fullName As String) As String Static id As Integer = -1 id += 1 Dim ext = Path.GetExtension(fullName) Dim baseName = Path.GetFileNameWithoutExtension(fullName) Return Path.Combine(_DownloadDir.FullName, String.Concat(baseName, "_", id, ext)) End Function Private Sub btHTTPDownload_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles btHTTPDownload.Click Dim Src = cmbHTTP.SelectedItem.ToString _Download(HttpWebRequest.Create(Src), InsertID("Webpage.htm")) End Sub Private Sub btFileDownload_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles btFileDownload.Click Dim Src = cmbFTP.SelectedItem.ToString _Download(FtpWebRequest.Create(Src), InsertID(Src)) End Sub Private Sub Download(ByVal Request As WebRequest, ByVal Dest As String) ' HttpWebRequest und FtpWebRequest werden gleich behandelt Dim Filename = Path.GetFileName(Dest) _DisplayMessage.RunGui("Begin Download", Tab, Request.RequestUri.AbsoluteUri, " " & _ "-> ", Filename, Lf) Using Response = Request.GetResponse(), Reader = Response.GetResponseStream(), Writer _ = New IO.FileStream(Dest, FileMode.Create) Reader.WriteTo(Writer) End Using _DisplayMessage.RunGui("Download finished", Tab, Filename, Lf) End Sub End Class ' --------------- Ende Datei frmWebDownload.vb --------------- ' ---------------- Anfang Datei modHelpers.vb ---------------- Imports System.Runtime.CompilerServices Public Module modHelpers <Extension()> _ Public Sub RunAsync(ByVal Action As [Delegate], ByVal ParamArray Args As Object()) ' Einfaches "Zwischenschalten" der RunAsync-Methode verlagert die Action in einen ' eigenen Thread ' Nicht verwechseln mit der "Zurückverlagerung" durch Control.BeginInvoke(Delegate, Arg)!! With Action.GetType Dim Mtd = .GetMethod("BeginInvoke") Mtd.Invoke(Action, Args) End With End Sub End Module ' ----------------- Ende Datei modHelpers.vb ----------------- ' ----------------- Anfang Datei StreamX.vb ----------------- Imports System.Runtime.CompilerServices Imports System.IO Public Module StreamX ''' <summary> kopiert von einem Stream in einen anderen </summary> ''' <remarks> ''' Es gibt Streams ohne festgelegtes Ende (zB. NetworkStream). ''' In solchem Fall **muß** 'count' angegeben werden. ''' </remarks> <Extension()> _ Public Sub WriteTo( _ ByVal readStream As Stream, _ ByVal writeStream As Stream, _ Optional ByVal count As Long = -1, _ Optional ByVal bufSize As Integer = Short.MaxValue) Dim buf(bufSize - 1) As Byte If count < 0 AndAlso readStream.CanSeek Then count = readStream.Length - readStream.Position End If If count < 0 Then ' Durch 0-Byte-Lesevorgang terminierte Kopier-Schleife ' Ein NetworkStream würde ein Timeout-Problem verursachen Do Dim portion = readStream.Read(buf, 0, bufSize) If portion = 0 Then Return writeStream.Write(buf, 0, portion) Loop Else ' zähler-gesteuerte Kopier-Schleife Do If count < bufSize Then bufSize = CInt(count) Dim portion = readStream.Read(buf, 0, bufSize) If portion = 0 Then Throw New ArgumentException("Die angegebene Anzahl " & _ "Bytes konnte nicht aus dem Lese-Stream gelesen werden", "readStream " & _ "+ count") count -= portion writeStream.Write(buf, 0, portion) Loop Until count = 0 End If End Sub End Module ' ------------------ Ende Datei StreamX.vb ------------------ ' ----------- Ende Projektdatei WebDownload.vbproj ----------- ' ------------ Ende Projektgruppe WebDownload.sln ------------
Diskussion
Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.
Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.