通过 .NET FileStreamResult 和 Web 流式传输 S3 文件 API
Stream S3 file via .NET FileStreamResult and Web API
我有一个代码片段应该使用文件流下载 S3 文件:
public async Task<FileStreamResult> DownloadReportFileAsFileStream(String fileName)
{
var request = new GetObjectRequest { BucketName = this.BucketName, Key = fileName };
using var response = await this.S3Client.GetObjectAsync(request);
var (mimeType, originalName) = response.Metadata.ExtractKnownMetaData();
return new FileStreamResult(response.ResponseStream, mimeType) { FileDownloadName = originalName };
}
似乎是合法的,但这段代码以某种方式抛出异常。这是堆栈跟踪的顶部片段:
System.NotSupportedException: The ReadAsync method cannot be called when another read operation is pending.
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
at System.Net.Http.HttpConnection.ReadAsync(Memory`1 destination)
奇怪的是,如果我将 s3 响应流读入内存,一切正常(除了立即处理内存中的文件内容):
// FileStorage method to read the file data as a byte array.
public async Task<Byte[]> DownloadReportFileAsByteArray(String fileName)
{
var request = new GetObjectRequest { BucketName = this.BucketName, Key = fileName };
using var response = await this.S3Client.GetObjectAsync(request);
await using var stream = response.ResponseStream;
await using var memory = new MemoryStream();
await stream.CopyToAsync(memory);
return memory.ToArray();
}
...
// returns a FileContentResult object from the file byte array.
public async Task<FileContentResult> DownloadReportS3(DownloadReportRequest request)
{
var bytes = await this.ReportFileStorage.DownloadReportFileAsByteArray(request.Id);
var (mimeType, originalName) = await this.ReportFileStorage.GetReportFileMetaData(request.Id);
return new FileContentResult(bytes, new MediaTypeHeaderValue(mimeType))
{
FileDownloadName = originalName
};
}
流式传输方法无法正常工作是否有原因?解决方法将非常适用。
我不应该对响应对象使用 using
语句:
public async Task<FileStreamResult> DownloadReportFileAsFileStream(String fileName)
{
var request = new GetObjectRequest { BucketName = this.BucketName, Key = fileName };
var response = await this.S3Client.GetObjectAsync(request);
var (mimeType, originalName) = response.Metadata.ExtractKnownMetaData();
return new FileStreamResult(response.ResponseStream, mimeType) { FileDownloadName = originalName };
}
似乎 FileStreamResult
将在内部处理流处理。
我有一个代码片段应该使用文件流下载 S3 文件:
public async Task<FileStreamResult> DownloadReportFileAsFileStream(String fileName)
{
var request = new GetObjectRequest { BucketName = this.BucketName, Key = fileName };
using var response = await this.S3Client.GetObjectAsync(request);
var (mimeType, originalName) = response.Metadata.ExtractKnownMetaData();
return new FileStreamResult(response.ResponseStream, mimeType) { FileDownloadName = originalName };
}
似乎是合法的,但这段代码以某种方式抛出异常。这是堆栈跟踪的顶部片段:
System.NotSupportedException: The ReadAsync method cannot be called when another read operation is pending.
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
at System.Net.Http.HttpConnection.ReadAsync(Memory`1 destination)
奇怪的是,如果我将 s3 响应流读入内存,一切正常(除了立即处理内存中的文件内容):
// FileStorage method to read the file data as a byte array.
public async Task<Byte[]> DownloadReportFileAsByteArray(String fileName)
{
var request = new GetObjectRequest { BucketName = this.BucketName, Key = fileName };
using var response = await this.S3Client.GetObjectAsync(request);
await using var stream = response.ResponseStream;
await using var memory = new MemoryStream();
await stream.CopyToAsync(memory);
return memory.ToArray();
}
...
// returns a FileContentResult object from the file byte array.
public async Task<FileContentResult> DownloadReportS3(DownloadReportRequest request)
{
var bytes = await this.ReportFileStorage.DownloadReportFileAsByteArray(request.Id);
var (mimeType, originalName) = await this.ReportFileStorage.GetReportFileMetaData(request.Id);
return new FileContentResult(bytes, new MediaTypeHeaderValue(mimeType))
{
FileDownloadName = originalName
};
}
流式传输方法无法正常工作是否有原因?解决方法将非常适用。
我不应该对响应对象使用 using
语句:
public async Task<FileStreamResult> DownloadReportFileAsFileStream(String fileName)
{
var request = new GetObjectRequest { BucketName = this.BucketName, Key = fileName };
var response = await this.S3Client.GetObjectAsync(request);
var (mimeType, originalName) = response.Metadata.ExtractKnownMetaData();
return new FileStreamResult(response.ResponseStream, mimeType) { FileDownloadName = originalName };
}
似乎 FileStreamResult
将在内部处理流处理。