2023-08-23 16:28:45 -04:00
using System.Collections.Generic ;
2018-05-29 19:45:25 -04:00
using static Vanara . PInvoke . BITS ;
2023-03-31 11:47:53 -04:00
namespace Vanara.IO ;
/// <summary>Information about a file in a background copy job.</summary>
public class BackgroundCopyFileInfo
2018-05-29 19:45:25 -04:00
{
2023-03-31 11:47:53 -04:00
internal BG_FILE_INFO fi ;
2018-05-29 19:45:25 -04:00
2023-08-23 16:28:45 -04:00
private readonly IBackgroundCopyFile ? iFile ;
2018-05-29 19:45:25 -04:00
2023-08-23 16:28:45 -04:00
internal BackgroundCopyFileInfo ( IBackgroundCopyFile ibgfile ) = > iFile = ibgfile ;
2018-05-29 19:45:25 -04:00
2023-08-23 16:28:45 -04:00
internal BackgroundCopyFileInfo ( BG_FILE_INFO bgfi ) = > fi = bgfi ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Retrieves the ranges that you want to download from the remote file.</summary>
/// <value>The file copy ranges.</value>
public IEnumerable < BackgroundCopyFileRange > FileRanges
{
get
2018-05-29 19:45:25 -04:00
{
2023-03-31 11:47:53 -04:00
IFile2 . GetFileRanges ( out var cnt , out var rng ) ;
return rng . ToEnumerable < BackgroundCopyFileRange > ( ( int ) cnt ) ;
2018-05-29 19:45:25 -04:00
}
2023-03-31 11:47:53 -04:00
}
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Returns the set of file ranges that have been downloaded.</summary>
/// <value>The file copy ranges that have been downloaded. Ranges will be merged together as much as possible. The ranges are ordered by offset.</value>
public IEnumerable < BackgroundCopyFileRange > FilledFileRanges
{
get
2018-05-29 19:45:25 -04:00
{
2023-03-31 11:47:53 -04:00
IFile6 . GetFilledFileRanges ( out var cnt , out var rng ) ;
return rng . ToEnumerable < BackgroundCopyFileRange > ( ( int ) cnt ) ;
2018-05-29 19:45:25 -04:00
}
2023-03-31 11:47:53 -04:00
}
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets or sets a value indicating whether the contents of the file are valid.</summary>
/// <value><c>true</c> if the file content is valid; otherwise, <c>false</c>.</value>
public bool IsFileContentValid { get = > IFile3 . GetValidationState ( ) ; set = > IFile3 . SetValidationState ( value ) ; }
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>
/// Size of the file in bytes. If the value is -1, the total size of the file has not been determined. BITS does not set this value if it cannot
/// determine the size of the file. For example, if the specified file or server does not exist, BITS cannot determine the size of the file. If you are
/// downloading ranges from a file, BytesTotal reflects the total number of bytes you want to download from the file.
/// </summary>
public long Length = > ( long ) CopyProgress . BytesTotal ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Retrieves the local name of the file.</summary>
public string LocalFilePath
{
get = > iFile is null ? fi . LocalName : iFile . GetLocalName ( ) ;
set
2018-05-29 19:45:25 -04:00
{
2023-03-31 11:47:53 -04:00
if ( iFile is not null )
throw new InvalidOperationException ( "You cannot change the LocalFilePath property on CurrentFileSet results." ) ;
fi . LocalName = value ;
2018-05-29 19:45:25 -04:00
}
2023-03-31 11:47:53 -04:00
}
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets the amount of file data downloaded from the originating server.</summary>
public ulong OriginServerDownloadBytes { get { IFile4 . GetPeerDownloadStats ( out var o , out var _ ) ; return o ; } }
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets the amount of file data downloaded from a peer-to-peer source.</summary>
public ulong PeerDownloadBytes { get { IFile4 . GetPeerDownloadStats ( out var _ , out var p ) ; return p ; } }
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets the percentage of the transfer that has completed.</summary>
public float PercentComplete
{
get
2018-05-29 19:45:25 -04:00
{
2023-03-31 11:47:53 -04:00
var p = CopyProgress ;
return p . Completed | | p . BytesTotal = = 0 ? 100.0F : p . BytesTransferred * 100.0F / p . BytesTotal ;
2018-05-29 19:45:25 -04:00
}
2023-03-31 11:47:53 -04:00
}
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Retrieves the remote name of the file.</summary>
public string RemoteFilePath
{
get = > iFile is null ? fi . RemoteName : iFile . GetRemoteName ( ) ;
set
2018-05-29 19:45:25 -04:00
{
2023-03-31 11:47:53 -04:00
fi . RemoteName = value ;
( iFile as IBackgroundCopyFile2 ) ? . SetRemoteName ( value ) ;
2018-05-29 19:45:25 -04:00
}
2023-03-31 11:47:53 -04:00
}
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets or sets the full set of HTTP response headers from the server's last HTTP response packet.</summary>
/// <value>The response headers.</value>
public string ResponseHeaders
{
get
{
var hdr = IFile5 . GetProperty ( BITS_FILE_PROPERTY_ID . BITS_FILE_PROPERTY_ID_HTTP_RESPONSE_HEADERS ) ;
return hdr . String ;
}
set
2018-05-29 19:45:25 -04:00
{
2023-03-31 11:47:53 -04:00
var hdr = new BITS_FILE_PROPERTY_VALUE { String = value } ;
IFile5 . SetProperty ( BITS_FILE_PROPERTY_ID . BITS_FILE_PROPERTY_ID_HTTP_RESPONSE_HEADERS , hdr ) ;
2018-05-29 19:45:25 -04:00
}
2023-03-31 11:47:53 -04:00
}
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets the full path of the temporary file that contains the content of the download.</summary>
public string TemporaryName = > IFile3 . GetTemporaryName ( ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>
/// For downloads, the value is TRUE if the file is available to the user; otherwise, the value is FALSE. Files are available to the user after calling
/// the <see cref="BackgroundCopyJob.Complete"/> method. If the <see cref="BackgroundCopyJob.Complete"/> method generates a transient error, those files
/// processed before the error occurred are available to the user; the others are not. Use the Completed property to determine if the file is available
/// to the user when Complete fails. For uploads, the value is TRUE when the file upload is complete; otherwise, the value is FALSE.
/// </summary>
public bool TransferCompleted = > CopyProgress . Completed ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets the number of bytes transferred.</summary>
public long BytesTransferred = > ( long ) CopyProgress . BytesTransferred ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Gets a value that determines if any part of the file was downloaded from a peer.</summary>
/// <value>Is TRUE if any part of the file was downloaded from a peer; otherwise, FALSE.</value>
public bool IsDownloadedFromPeer = > IFile3 . IsDownloadedFromPeer ( ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Retrieves the progress of the file transfer.</summary>
internal BG_FILE_PROGRESS CopyProgress = > iFile ? . GetProgress ( ) ? ? throw new InvalidOperationException ( "You can only get the CopyProgress on CurrentFileSet results." ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
private IBackgroundCopyFile2 IFile2 = > GetDerived < IBackgroundCopyFile2 > ( ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
private IBackgroundCopyFile3 IFile3 = > GetDerived < IBackgroundCopyFile3 > ( ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
private IBackgroundCopyFile4 IFile4 = > GetDerived < IBackgroundCopyFile4 > ( ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
private IBackgroundCopyFile5 IFile5 = > GetDerived < IBackgroundCopyFile5 > ( ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
private IBackgroundCopyFile6 IFile6 = > GetDerived < IBackgroundCopyFile6 > ( ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Adds a new set of file ranges to be prioritized for download.</summary>
/// <param name="ranges">
/// An array of file ranges to be downloaded. Requested ranges are allowed to overlap previously downloaded (or pending) ranges. Ranges are automatically
/// split into non-overlapping ranges.
/// </param>
2023-08-23 16:28:45 -04:00
public void RequestFileRanges ( BackgroundCopyFileRange [ ] ranges ) = > IFile6 . RequestFileRanges ( ( uint ) ranges . Length , Array . ConvertAll ( ranges , r = > r . fr ) ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Returns a <see cref="System.String" /> that represents this instance.</summary>
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
public override string ToString ( ) = > $"{LocalFilePath} => {RemoteFilePath}" ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Specifies a position to prioritize downloading missing data from.</summary>
/// <param name="offset">Specifies the new position to prioritize downloading missing data from.</param>
public void UpdateDownloadPosition ( ulong offset ) = > IFile6 . UpdateDownloadPosition ( offset ) ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
private T GetDerived < T > ( ) where T : class = > iFile as T ? ? throw new PlatformNotSupportedException ( ) ;
}
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Identifies a range of bytes to download from a file.</summary>
[StructLayout(LayoutKind.Sequential)]
public class BackgroundCopyFileRange
{
internal BG_FILE_RANGE fr ;
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Zero-based offset to the beginning of the range of bytes to download from a file.</summary>
public ulong InitialOffset { get = > fr . InitialOffset ; set = > fr . InitialOffset = value ; }
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>
/// The length of the range, in bytes. Do not specify a zero byte length. To indicate that the range extends to the end of the file, specify <c>BG_LENGTH_TO_EOF</c>.
/// </summary>
public ulong Length { get = > fr . Length ; set = > fr . Length = value ; }
2018-05-29 19:45:25 -04:00
2023-03-31 11:47:53 -04:00
/// <summary>Performs an implicit conversion from <see cref="BG_FILE_RANGE"/> to <see cref="BackgroundCopyFileRange"/>.</summary>
/// <param name="p">The BG_FILE_RANGE instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator BackgroundCopyFileRange ( BG_FILE_RANGE p ) = > new ( ) { fr = p } ;
2018-05-29 19:45:25 -04:00
}