首页 文章

使用Amazon S3 API - ASP.MVC上的SDK直接下载文件的更好方法

提问于
浏览
0

亚马逊提供了大量的文档,但是有很多文档我丢失了,所以这是我目前的上传/下载文件服务 . 上传按预期工作,但在下载时我必须将文件下载到物理路径,然后将下载提供给用户,我没有多少使用流的经验 . 这是连接到Amazon API的FileManagerService类 .

using Amazon.S3;
using Amazon.S3.Model;
public class FileManagerService
    {
        public FileManagerService()
        {
            string serverPath = HttpContext.Current.Server.MapPath("~/");
            string uploadPath = Path.Combine(serverPath, "FileUploads");
            Directory.CreateDirectory(uploadPath);
            UploadDirectory = uploadPath;
        }
        private string UploadDirectory { get; set; }

        private docucloudEntities db = new docucloudEntities();

        private IAmazonS3 S3Client = new AmazonS3Client();

        private string S3Bucket = "bucketname";

        public async Task<string> DownloadFile(string AmazonFileKey, string FileName)
        {
            var fileRequest = new GetObjectRequest
            {
                BucketName = S3Bucket,
                Key = AmazonFileKey
            };

            var localRoute = Path.Combine(UploadDirectory, FileName);

            using (var fileObject = await S3Client.GetObjectAsync(fileRequest))
            {
                if (fileObject.HttpStatusCode == HttpStatusCode.OK)
                {
                    fileObject.WriteResponseStreamToFile(localRoute);
                }
            }
            return localRoute;
        }
    }

这个方法返回字符串,它还没有完成try catch块,但它目前有效 . 这是我的控制器方法,将文件下载到客户端:

public class FileManagerController : Controller
{
    private FileManagerService FileService = new FileManagerService();

    public async Task<ActionResult> DownloadFileAmazon(long FileId)
    {
        if (db.Archivos.Any(i => i.ArchivoID == FileId))
        {
            var archivo = db.Archivos.Single(i => i.ArchivoID == FileId);
            var rutaarchivo = await FileService.DownloadFile(archivo.Ruta, archivo.Nombre);
            if (System.IO.File.Exists(rutaarchivo))
            {
                var fileBytes = System.IO.File.ReadAllBytes(rutaarchivo);
                var response = new FileContentResult(fileBytes, "application/octet-stream");
                response.FileDownloadName = archivo.Nombre;
                System.IO.File.Delete(rutaarchivo);
                return response;
            }else
            {
                return HttpNotFound();
            }
        }else
        {
            return HttpNotFound();
        }
    }
}

所以在控制器上我读取文件字节并在删除文件后提供下载,但这可能导致性能降低,有一种实现直接下载的方法 .

1 回答

  • 0

    据我所知,即使文档这样说,也没有理由处理 GetObjectResponse (返回类型 GetObjectAsync ) . GetObjectResponse 未实现 IDisposable 但继承 StreamResponse . 但是,据我所知,it's only disposing the ResponseStream . 因此,您可以将来自 GetObjectResponsefileObject.ResponseStream )的流与 Headers ( fileObject.Headers.ContentType )中的 ContentType 一起返回,然后您可以将其作为控制器中的文件返回:

    [HttpGet]
    [Route("blob/{filename}")]
    public async Task<IActionResult> GetFile(string filename)
    {
        try
        {
            var file = await _fileStorageService.GetBlobAsync(filename);
    
            return File(file.Stream, file.ContentType);
        }
        catch (Exception ex)
        {
            // Handle exceptions
        }
    }
    

    FileResult 将在写入文件后处理流,以便流最终得到处理 .

相关问题