寻找替代方法来编写 azure 块 blob 的一部分,因为不支持查找

Looking for alternative to writing part of a azure block blob as seeking is not supported

我有一些遗留代码用于 运行 System.IO 文件系统。

问题是现在不支持seeking了,改成在azure上用blockBlob

    var contentLength = Math.Max(0, blob.Properties.Length);
    var request = new HttpRequestMessage { RequestUri = new Uri(source.Metadata.MediaSrc) };
    request.Headers.Range = new RangeHeaderValue();
    request.Headers.Range.Ranges.Add(new RangeItemHeaderValue(contentLength, null));

    var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

    response.EnsureSuccessStatusCode();

    using (var stream = await blob.OpenWriteAsync(cancellationToken))
    {
        if (contentLength > 0)
        {
            stream.Seek(contentLength, SeekOrigin.Begin);
        }
        try
        {
            using (var responeStream = await response.Content.ReadAsStreamAsync())
            {
                await responeStream.CopyToAsync(stream, 81920, cancellationToken);
            }
        }                                       
        finally
        {
            await stream.FlushAsync();
            stream.Dispose();
        }
    }

基本上代码是用来写大文件的,当文件的一部分已经写完了,它可以从停止的地方继续写。

我正在寻找做过类似事情的人的例子,并更改代码以找到最后提交的块并从那里开始编写

我用了下面的方法。

var blocksize = 0L;
var list = new List<string>();
if (contentLength > 0)
{
    var blocks = await blob.DownloadBlockListAsync(BlockListingFilter.Committed, null, null, null);
    contentLength = blocks.Aggregate(0L, (seed, item) => seed + item.Length);
    blocksize = blocks.First().Length;
    list.AddRange(blocks.Select(k => k.Name));
}

_logger.LogTrace("Item {id} with contentLenght {contentLenght}:{expectedContentLength} is starting to download", a.Value.Source.Id, contentLength, expectedContentLength);


var request = new HttpRequestMessage { RequestUri = new Uri(source.Metadata.MediaSrc) };
request.Headers.Range = new RangeHeaderValue();// (info.Length, Math.Min(length, info.Length+ BlockDownSize));
request.Headers.Range.Ranges.Add(new RangeItemHeaderValue(contentLength, null));

var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

response.EnsureSuccessStatusCode();

    private static async Task DownloadMissingBlocksAsync(CloudBlockBlob blob, long totalMissing, long blocksize, List<string> list, HttpResponseMessage response, CancellationToken cancellationToken)
    {
        var buffer = new byte[blocksize];
        // var read = -1;
        var blockIdPrefix = Guid.NewGuid().ToString("N") + "-";

        using (var responeStream = await response.Content.ReadAsStreamAsync())
        {
            try
            {


                while (totalMissing > 0)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var missingRead = buffer.Length;

                    while (Math.Min((int)totalMissing, (int)missingRead) > 0)
                    {
                        var read = await responeStream.ReadAsync(buffer, buffer.Length - missingRead, Math.Min((int)totalMissing, (int)missingRead));
                        missingRead -= read;
                        totalMissing -= read;
                    }

                    string blockIdSuffix = list.Count.ToString("D6", CultureInfo.InvariantCulture);
                    byte[] blockIdInBytes = Encoding.UTF8.GetBytes(blockIdPrefix + blockIdSuffix);
                    var blockid = Convert.ToBase64String(blockIdInBytes);

                    await blob.PutBlockAsync(blockid, new MemoryStream(buffer, 0, buffer.Length - missingRead), null);
                    list.Add(blockid);
                }
            } 
            finally
            {
                await blob.PutBlockListAsync(list);
            }

        }


    }