Exemplo n.º 1
0
        private async Task FillBuffer(PipeWriter writer, CancellationToken cancellationToken)
        {
            long offset = 0;

            try
            {
                while (offset < fileEntry.Size)
                {
                    var pipeBuffer = writer.GetMemory(maxMessageSize);

                    try
                    {
                        using var readSegmentCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                        readSegmentCts.CancelAfter(segmentFetchTimeout);

                        var length = (int)Math.Min(maxMessageSize, fileEntry.Size - offset);
                        var base64 = await jsModule.ReadDataAsync(elementRef, fileEntry.Id, offset, length, cancellationToken);

                        var bytes = Convert.FromBase64String(base64);

                        if (bytes is null || bytes.Length != length)
                        {
                            throw new InvalidOperationException(
                                      $"A segment with size {bytes?.Length ?? 0} bytes was received, but {length} bytes were expected.");
                        }

                        bytes.CopyTo(pipeBuffer);
                        writer.Advance(length);
                        offset += length;

                        var result = await writer.FlushAsync(cancellationToken);

                        await Task.WhenAll(
                            fileEntryNotifier.UpdateFileWrittenAsync(fileEntry, offset, bytes),
                            fileEntryNotifier.UpdateFileProgressAsync(fileEntry, bytes.Length));

                        if (result.IsCompleted)
                        {
                            break;
                        }
                    }
                    catch (Exception e)
                    {
                        await writer.CompleteAsync(e);

                        return;
                    }
                }
            }
            finally
            {
                await fileEntryNotifier.UpdateFileEndedAsync(fileEntry, offset == fileEntry.Size);
            }

            await writer.CompleteAsync();
        }
Exemplo n.º 2
0
        private async Task FillBuffer(PipeWriter writer, CancellationToken cancellationToken)
        {
            if (maxFileSize < fileEntry.Size)
            {
                await fileEntryNotifier.UpdateFileEndedAsync(fileEntry, false, FileInvalidReason.MaxLengthExceeded);

                return;
            }

            long position = 0;

            try
            {
                while (position < fileEntry.Size)
                {
                    var pipeBuffer = writer.GetMemory(maxMessageSize);

                    try
                    {
                        using var readSegmentCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                        readSegmentCts.CancelAfter(segmentFetchTimeout);

                        var length = (int)Math.Min(maxMessageSize, fileEntry.Size - position);
                        var base64 = await jsModule.ReadDataAsync(elementRef, fileEntry.Id, position, length, cancellationToken);

                        var bytes = Convert.FromBase64String(base64);

                        if (bytes is null || bytes.Length != length)
                        {
                            await fileEntryNotifier.UpdateFileEndedAsync(fileEntry, false, FileInvalidReason.UnexpectedBufferChunkLength);

                            await writer.CompleteAsync();

                            return;
                        }

                        bytes.CopyTo(pipeBuffer);
                        writer.Advance(length);
                        position += length;

                        var result = await writer.FlushAsync(cancellationToken);

                        await Task.WhenAll(
                            fileEntryNotifier.UpdateFileWrittenAsync(fileEntry, position, bytes),
                            fileEntryNotifier.UpdateFileProgressAsync(fileEntry, bytes.Length));

                        if (result.IsCompleted)
                        {
                            break;
                        }
                    }
                    catch (OperationCanceledException oce)
                    {
                        await writer.CompleteAsync(oce);

                        await fileEntryNotifier.UpdateFileEndedAsync(fileEntry, false, FileInvalidReason.TaskCancelled);

                        return;
                    }
                    catch (Exception e)
                    {
                        await writer.CompleteAsync(e);
                    }
                }
            }
            finally
            {
                if (!cancellationToken.IsCancellationRequested)
                {
                    var success = position == fileEntry.Size;
                    var overMaxBufferChunkLength = position > fileEntry.Size;
                    var fileInvalidReason        = success
                        ? FileInvalidReason.None
                        : overMaxBufferChunkLength
                            ? FileInvalidReason.UnexpectedBufferChunkLength
                            : FileInvalidReason.UnexpectedError;

                    await fileEntryNotifier.UpdateFileEndedAsync(fileEntry, success, fileInvalidReason);
                }
            }

            await writer.CompleteAsync();
        }