in src/AlibabaCloud.OSS.V2/Client.Extensions.cs [125:225]
public async Task<Models.GetObjectResult> GetObjectToFileAsync(
Models.GetObjectRequest request,
string filepath,
OperationOptions? options = null,
CancellationToken cancellationToken = default
)
{
var (retry, readTimeout) = _clientImpl.GetRuntimeContext(options);
Models.GetObjectResult? result;
Exception? lastEx = null;
var i = 0;
WriteOnlyHashStream? crcTracker = null;
Stream? progTracker = null;
var trackers = new List<Stream>();
if (_clientImpl.Options.FeatureFlags.HasFlag(FeatureFlagsType.EnableCrc64CheckDownload))
{
crcTracker = new WriteOnlyHashStream(new HashCrc64(0));
trackers.Add(crcTracker);
}
do
{
result = await GetObjectAsync(request, options, cancellationToken).ConfigureAwait(false);
lastEx = null;
if (request.ProgressFn != null && progTracker == null)
{
progTracker = new ProgressStream(request.ProgressFn, result.ContentLength ?? -1);
trackers.Add(progTracker);
}
using var cts = new CancellationTokenSource(readTimeout);
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, cancellationToken);
try
{
using var fs = File.Open(filepath, FileMode.Create);
byte[] buffer = new byte[Defaults.DefaultCopyBufferSize];
int count;
while ((count = await result.Body!.ReadAsync(buffer, 0, buffer.Length, linkedCts.Token).ConfigureAwait(false)) != 0)
{
await fs.WriteAsync(buffer, 0, count, linkedCts.Token).ConfigureAwait(false);
foreach (var t in trackers)
{
t.Write(buffer, 0, count);
}
cts.CancelAfter(readTimeout);
}
if (crcTracker != null)
{
if (result.Headers.TryGetValue("x-oss-hash-crc64ecma", out var scrc))
{
var val = crcTracker.Hash.Final();
var ccrc = Convert.ToString(BitConverter.ToUInt64(val, 0), CultureInfo.InvariantCulture);
if (!string.Equals(ccrc, scrc))
{
result.Headers.TryGetValue("x-oss-request-id", out var requestId);
throw new InconsistentException(ccrc, scrc, requestId ?? "");
}
}
}
break;
}
catch (OperationCanceledException e)
{
lastEx = e;
if (cts.IsCancellationRequested)
{
lastEx = new RequestTimeoutException(
$"The operation was cancelled because it exceeded the configured timeout of {readTimeout:g}. ", e);
}
else if (cancellationToken.IsCancellationRequested)
{
break;
}
}
catch (Exception e)
{
lastEx = e;
}
finally
{
result.Body!.Dispose();
result.InnerBody = null;
if (lastEx != null)
{
foreach (var t in trackers)
{
t.Seek(0, SeekOrigin.Begin);
}
}
}
} while (++i < retry);
if (lastEx != null)
{
throw lastEx;
}
return result;
}