0

我有一个从 OpenWriter 方法创建的 BlobStream。

var blob = CloudContainer.GetBlobReference(name));
if (blob == null)
{
   return null;
}

return blob.OpenWrite();

使用这个流我想寻找或设置位置,但每次我这样做我都会得到一个 NotSupportedException。在做了一些研究后,我发现 canSeek 设置为 false,这导致了这个问题。但是,仅当长度未知时,CanSeek 才为假。但是当我运行调试器时长度是已知的。

为什么 CanSeek 是假的?我怎样才能让它设置为真?

4

2 回答 2

3

blobclient.OpenRead您可以使用以下代码返回包装的流,而不是从返回。我们的要求是从负载平衡的文件服务器启用并行和可恢复的 Azure blob 下载。代码中可能存在一些问题,请检查并根据需要修复它们。

在控制器中返回controller.File(stream, contentType, filename, true)时,从最后一个参数开始,它会使用传入的 contentrangeheader 的值进行enableRangeProcessing=true验证stream.CanSeek=true和调用。stream.Seekrange.from

所以包装源return new SeekableBlobReadStream(blobclient)并将其发送到控制器。

internal class SeekableBlobReadStream : Stream
{
    private Stream stream;
    private readonly BlobBaseClient client;
    private readonly BlobProperties properties;

    public SeekableBlobReadStream(BlobBaseClient client)
    {
        properties = client.GetProperties().Value;
        this.client = client;
    }

    private void PrepareStream(long position = 0)
    {
        if (stream == null || position != 0)
        {
            if (stream != null)
                stream.Dispose();
            stream = client.OpenRead(new BlobOpenReadOptions(false) { Position = position });
        }
    }

    public override bool CanRead => true;

    public override bool CanSeek => true;

    public override bool CanWrite => false;

    public override long Length => properties.ContentLength;

    public override long Position
    {
        get => (stream?.Position).GetValueOrDefault();
        set => PrepareStream(value);
    }

    public override void Flush()
    {
        PrepareStream();
        stream.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        PrepareStream();
        return stream.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        switch (origin)
        {
            case SeekOrigin.Current:
                offset = Position + offset;
                break;
            case SeekOrigin.End:
                offset = Length - offset;
                break;
        }
        PrepareStream(offset);
        return stream.Position;
    }

    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }
}
于 2020-09-09T16:29:50.247 回答
1

您可以在页面 blob 中查找 - 在BlobWriteStreamBase类中有明确的支持。

我认为您还可以使用 HTTP 标头读取和写入块 blob 的指定部分Range,这实际上与查找相同。但我认为你必须自己实施。

于 2013-05-16T14:21:52.270 回答