我正在开发 Asp.Net Core 2 Web Api,我必须创建一个端点来下载文件。该文件不是公开的,因此我无法使用谷歌存储对象的
MediaLink
属性。我正在使用他们的 C# 库。
在这段代码中,您将看到下面的
_storageClient
是这样创建的:_storageClient = StorageClient.Create(cred);
。客户端正在工作,只是显示它是哪个类。
[HttpGet("DownloadFile/{clientId}/{fileId}")]
public async Task<IActionResult> DownloadFile([FromRoute] long fileId, long clientId)
{
// here there are a bunch of logic and permissions. Not relevant to the quest
var stream = new MemoryStream();
try
{
stream.Position = 0;
var obj = _storageClient.GetObject("bucket name here", "file.png");
_storageClient.DownloadObject(obj, stream);
var response = File(stream, obj.ContentType, "file.png"); // FileStreamResult
return response;
}
catch (Exception ex)
{
throw;
}
}
变量
obj
正常。所有属性均按预期填充。 stream
似乎已正确填充。它有长度和一切,但它返回给我一个 500 错误,我什至无法捕获。
我看不到我做错了什么,也许我是如何使用内存流的,但我什至无法捕获错误。
感谢您的帮助
您正在倒带流,但在向其中写入任何内容之前 - 但之后您不倒带它。我希望这会导致空响应而不是 500 错误,但我至少会将
stream.Position
调用移至下载后:
var obj = _storageClient.GetObject("bucket name here", "file.png");
_storageClient.DownloadObject(obj, stream);
stream.Position = 0;
请注意,在下载之前您不需要获取对象元数据。你可以只使用:
_storageClient.DownloadObject("bucket name here", "file.png", stream);
stream.Position = 0;
解决方案可以如下所示。
[HttpGet("get-file")]
public ActionResult GetFile()
{
var storageClient = ...;
byte[] buffer;
using (var memoryStream = new MemoryStream())
{
storageClient.DownloadObject("bucket name here"+"/my-file.jpg", memoryStream);
buffer = memoryStream.ToArray();
}
return File(buffer, "image/jpeg", "my-file.jpg");
}
我有相同的代码按预期工作,当多个用户下载较大尺寸的文件时,它会引发内存异常。有什么更好的方法可以在不加载到系统内存的情况下处理下载。我使用 GCP 云进行 api 服务和 gcp 云存储