public async Task GetObjectToFileAsync()

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;
        }