dotnet / winforms

Windows Forms is a .NET UI framework for building Windows desktop applications.
MIT License
4.42k stars 984 forks source link

Add Async versions of DownloadFile #11747

Open paul1956 opened 3 months ago

paul1956 commented 3 months ago

Background and motivation

In order to update Microsoft.VisualBasic.Devices.Network to use HttpClient a set of DownloadFileAsyc needed to be create but they are now Friend Shared. It would be useful if the Async versions were available to developers, and they are already written and tested.

API Proposal

It is possible to match all the current Microsoft.VisualBasic.Devices.Network.DownloadFile API but the set below is also reasonable. It is also possible to have many few using optional parameters. Some below are currently commented out as unnecessary for replacement of WebClient.

        ''' <summary>
        '''  Sends and receives a packet to and from the passed in Uri.
        '''  Maps older networkCredentials to HttpClientHandler.
        ''' </summary>
        ''' <param name="addressUri">Uri to the remote file.</param>
        ''' <param name="destinationFileName">Name and path of file where download is saved.</param>
        ''' <param name="networkCredentials">The credentials of the user performing the download.</param>
        ''' <param name="dialog">A ProgressDialog or Nothing.</param>
        ''' <param name="connectionTimeout">Time allotted before giving up on a connection.</param>
        ''' <param name="overwrite">Indicates whether or not the file should be overwritten if local file already exists.</param>
        ''' <param name="onUserCancel"></param>
        Friend Shared Function DownloadFileAsync(
            addressUri As Uri,
            destinationFileName As String,
            networkCredentials As ICredentials,
            dialog As ProgressDialog,
            connectionTimeout As Integer,
            overwrite As Boolean,
            onUserCancel As UICancelOption) As Task

        ''' <summary>
        '''  Downloads a file from the network to the specified path.
        ''' </summary>
        ''' <param name="addressUri">Uri to the remote file</param>
        ''' <param name="destinationFileName">Name and path of file where download is saved.</param>
        ''' <param name="userName">The name of the user performing the download.</param>
        ''' <param name="password">The user's password.</param>
        ''' <param name="dialog">A ProgressDialog or Nothing.</param>
        ''' <param name="connectionTimeout">Time allotted before giving up on a connection.</param>
        ''' <param name="overwrite">Indicates whether or not the file should be overwritten if local file already exists.</param>
        Friend Shared Async Function DownloadFileAsync(
            addressUri As Uri,
            destinationFileName As String,
            userName As String,
            password As String,
            dialog As ProgressDialog,
            connectionTimeout As Integer,
            overwrite As Boolean) As Task

        ''' <summary>
        '''  Downloads a file from the network to the specified path.
        ''' </summary>
        ''' <param name="addressUri">Uri to the remote file</param>
        ''' <param name="destinationFileName">Name and path of file where download is saved.</param>
        ''' <param name="userName">The name of the user performing the download.</param>
        ''' <param name="password">The user's password.</param>
        ''' <param name="dialog">ProgressDialog or Nothing.</param>
        ''' <param name="connectionTimeout">Time allotted before giving up on a connection.</param>
        ''' <param name="overwrite">Indicates whether or not the file should be overwritten if local file already exists.</param>
        ''' <param name="onUserCancel">Indicates what to do if user cancels dialog (either throw or do nothing).</param>
        Friend Shared Async Function DownloadFileAsync(
            addressUri As Uri,
            destinationFileName As String,
            userName As String,
            password As String,
            dialog As ProgressDialog,
            connectionTimeout As Integer,
            overwrite As Boolean,
            onUserCancel As UICancelOption) As Task

        ''' <summary>
        '''  Downloads a file from the network to the specified path.
        ''' </summary>
        ''' <param name="addressUri">Uri to the remote file</param>
        ''' <param name="destinationFileName">Name and path of file where download is saved.</param>
        ''' <param name="clientHandler">An HttpClientHandler of the user performing the download.</param>
        ''' <param name="dialog">Progress Dialog.</param>
        ''' <param name="connectionTimeout">Time allotted before giving up on a connection.</param>
        ''' <param name="overwrite">Indicates whether or not the file should be overwritten if local file already exists.</param>
        ''' <param name="onUserCancel">Indicates what to do if user cancels dialog (either throw or do nothing).</param>
        ''' <remarks>Calls to all the other overloads will come through here.</remarks>
        Friend Shared Async Function DownloadFileAsync(
            addressUri As Uri,
            destinationFileName As String,
            clientHandler As HttpClientHandler,
            dialog As ProgressDialog,
            connectionTimeout As Integer,
            overwrite As Boolean,
            onUserCancel As UICancelOption) As Task

        ''' <summary>
        '''  Downloads a file from the network to the specified path.
        ''' </summary>
        ''' <param name="address">Address to the remote file, http, ftp etc...</param>
        ''' <param name="destinationFileName">Name and path of file where download is saved.</param>
        ''' <param name="userName">The name of the user performing the download.</param>
        ''' <param name="password">The user's password.</param>
        ''' <param name="dialog">A ProgressDialog or Nothing.</param>
        ''' <param name="connectionTimeout">Time allotted before giving up on a connection.</param>
        ''' <param name="overwrite">Indicates whether or not the file should be overwritten if local file already exists.</param>
        Friend Shared Async Function DownloadFileAsync(
            address As String,
            destinationFileName As String,
            userName As String,
            password As String,
            dialog As ProgressDialog,
            connectionTimeout As Integer,
            overwrite As Boolean) As Task

        ''' <summary>
        '''  Downloads a file from the network to the specified path.
        ''' </summary>
        ''' <param name="address">Address to the remote file, http, ftp etc...</param>
        ''' <param name="destinationFileName">Name and path of file where download is saved.</param>
        ''' <param name="userName">The name of the user performing the download.</param>
        ''' <param name="password">The user's password.</param>
        ''' <param name="dialog">A ProgressDialog or Nothing.</param>
        ''' <param name="connectionTimeout">Time allotted before giving up on a connection.</param>
        ''' <param name="overwrite">Indicates whether or not the file should be overwritten if local file already exists.</param>
        ''' <param name="onUserCancel">Indicates what to do if user cancels dialog (either throw or do nothing).</param>
        Friend Shared Async Function DownloadFileAsync(
            address As String,
            destinationFileName As String,
            userName As String,
            password As String,
            dialog As ProgressDialog,
            connectionTimeout As Integer,
            overwrite As Boolean,
            onUserCancel As UICancelOption) As Task

        ''' <summary>
        '''  Downloads a file from the network to the specified path.
        ''' </summary>
        ''' <param name="addressUri">Uri to the remote file</param>
        ''' <param name="destinationFileName">Name and path of file where download is saved.</param>
        ''' <param name="networkCredentials">The credentials of the user performing the download.</param>
        ''' <param name="dialog">A ProgressDialog or Nothing.</param>
        ''' <param name="connectionTimeout">Time allotted before giving up on a connection.</param>
        ''' <param name="overwrite">Indicates whether or not the file should be overwritten if local file already exists.</param>
        ''' <remarks>
        '''  Function will Throw on unhandled exceptions.
        ''' </remarks>
        Friend Shared Async Function DownloadFileAsync(
            addressUri As Uri,
            destinationFileName As String,
            networkCredentials As ICredentials,
            dialog As ProgressDialog,
            connectionTimeout As Integer,
            overwrite As Boolean) As Task

API Usage

Dim t As Task = DownloadFileAsync(
  addressUri:=address,
  destinationFileName,
  networkCredentials,
  dialog,
  connectionTimeout,
  overwrite,
  onUserCancel)

Alternative Designs

Just a few Async API's with many optional parameters or exactly copy DownloadFile API's and make them all Async

Risks

There is already 100% test coverage in FixIssue#9807 PR so risk is minimal.

Will this feature affect UI controls?

No

merriemcgaw commented 3 months ago

@KlausLoeffelmann to investigate for .NET 10

paul1956 commented 3 months ago

@KlausLoeffelmann they are all implemented as Friend and 100% tested in my Download PR though you probably want to make some changes in API to support a cancellation token.

paul1956 commented 1 month ago

@JeremyKuhne any chance of API review