簡體   English   中英

如何在 ASP.NET Core 中下載文件?

[英]How to download a file in ASP.NET Core?

在 MVC 中,我們使用以下代碼下載文件。 在 ASP.NET core 中,如何實現呢?

    HttpResponse response = HttpContext.Current.Response;                 
    System.Net.WebClient net = new System.Net.WebClient();
    string link = path;
    response.ClearHeaders();
    response.Clear();
    response.Expires = 0;
    response.Buffer = true;
    response.AddHeader("Content-Disposition", "Attachment;FileName=a");
    response.ContentType = "APPLICATION/octet-stream";
    response.BinaryWrite(net.DownloadData(link));
    response.End();

您的控制器應該返回一個IActionResult ,並使用File方法,例如:

[HttpGet("download")]
public IActionResult GetBlobDownload([FromQuery] string link)
{
    var net = new System.Net.WebClient();
    var data = net.DownloadData(link);
    var content = new System.IO.MemoryStream(data);
    var contentType = "APPLICATION/octet-stream";
    var fileName = "something.bin";
    return File(content, contentType, fileName);
}

您可以嘗試以下代碼來下載文件。 它應該返回FileResult

public ActionResult DownloadDocument()
{
string filePath = "your file path";
string fileName = "your file name";
    
byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
    
return File(fileBytes, "application/force-download", fileName);
    
}

一個相對簡單的方法是使用內置的PhysicalFile結果,它適用於所有控制器: MS Docs:PhysicalFile

一個簡單的例子:

public IActionResult DownloadFile(string filePath)
{
     return PhysicalFile(filePath, MimeTypes.GetMimeType(filePath), Path.GetFileName(filePath));
}

當然,出於安全考慮,您永遠不應該公開這種 API。

我通常將實際文件路徑屏蔽在友好標識符后面,然后我用它來查找真實文件路徑(如果傳入了無效 ID,則返回 404),即:

[HttpGet("download-file/{fileId}")]
public IActionResult DownloadFile(int fileId)
{
    var filePath = GetFilePathFromId(fileId);
    if (filePath == null) return NotFound();
        
    return PhysicalFile(filePath, MimeTypes.GetMimeType(filePath), Path.GetFileName(filePath));
}

對於那些好奇的人, MimeTypes助手是來自 MimeKit 的一個很棒的小Nuget

這是我的 Medium 文章,逐步描述所有內容(還包括 GitHub 存儲庫): https ://medium.com/@tsafadi/download-a-file-with-asp-net-core-e23e8b198f74

任何方式這都是控制器的外觀:

[HttpGet]
public IActionResult DownloadFile()
{
    // Since this is just and example, I am using a local file located inside wwwroot
    // Afterwards file is converted into a stream
    var path = Path.Combine(_hostingEnvironment.WebRootPath, "Sample.xlsx");
    var fs = new FileStream(path, FileMode.Open);

    // Return the file. A byte array can also be used instead of a stream
    return File(fs, "application/octet-stream", "Sample.xlsx");
}

視圖內部:

$("button").click(function () {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "Download/DownloadFile", true);
    xhr.responseType = "blob";
    xhr.onload = function (e) {
        if (this.status == 200) {
            var blob = this.response;

            /* Get filename from Content-Disposition header */
            var filename = "";
            var disposition = xhr.getResponseHeader('Content-Disposition');
            if (disposition && disposition.indexOf('attachment') !== -1) {
                var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
                var matches = filenameRegex.exec(disposition);
                if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
            }

            // This does the trick
            var a = document.createElement('a');
            a.href = window.URL.createObjectURL(blob);
            a.download = filename;
            a.dispatchEvent(new MouseEvent('click'));
        }
    }
    xhr.send();
});

創建一個服務,比如 FileService。

public class FileService
{
    private readonly IHostingEnvironment _hostingEnvironment;
    constructor(IHostingEnvironment hostingEnvironment)
    {
        this._hostingEnvironment = hostingEnvironment;
    }
}

向文件的 FileService MimeType 添加方法

private string GetMimeType(string fileName)
{
    // Make Sure Microsoft.AspNetCore.StaticFiles Nuget Package is installed
    var provider = new FileExtensionContentTypeProvider();
    string contentType;
    if (!provider.TryGetContentType(fileName, out contentType))
    {
        contentType = "application/octet-stream";
    }
    return contentType;
}

現在添加一個下載文件的方法,

public FileContentResult GetFile(string filename) 
{
    var filepath = Path.Combine($"{this._environment.WebRootPath}\\path-to-required-folder\\{filename}");

    var mimeType = this.GetMimeType(filename); 

    byte[] fileBytes;

    if (File.Exists(filepath))
    {
        fileBytes = File.ReadAllBytes(filepath); 
    } 
    else
    {
        // Code to handle if file is not present
    }

    return new FileContentResult(fileBytes, mimeType)
    {
        FileDownloadName = filename
    };
}

現在添加控制器方法並在 FileService 中調用 GetFile 方法,

 public IActionResult DownloadFile(string filename) 
 {
    // call GetFile Method in service and return       
 }

Asp.net Core 2.1+ 示例(最佳實踐)

啟動.cs:

private readonly IHostingEnvironment _env;

public Startup(IConfiguration configuration, IHostingEnvironment env)
{
    Configuration = configuration;
    _env = env;
}

services.AddSingleton(_env.ContentRootFileProvider); //Inject IFileProvider

SomeService.cs:

private readonly IFileProvider _fileProvider;

public SomeService(IFileProvider fileProvider)
{
    _fileProvider = fileProvider;
}

public FileStreamResult GetFileAsStream()
{
    var stream = _fileProvider
        .GetFileInfo("RELATIVE PATH TO FILE FROM APP ROOT")
        .CreateReadStream();

    return new FileStreamResult(stream, "CONTENT-TYPE")
}

控制器將返回IActionResult

[HttpGet]
public IActionResult Get()
{
    return _someService.GetFileAsStream() ?? (IActionResult)NotFound();
}

Action 方法需要返回帶有文件流、字節[] 或虛擬路徑的 FileResult。 您還需要知道正在下載的文件的內容類型。 這是一個示例(快速/臟)實用程序方法。 示例視頻鏈接如何使用 asp.net core 下載文件

[Route("api/[controller]")]
public class DownloadController : Controller
{
    [HttpGet]
    public async Task<IActionResult> Download()
    {
        var path = @"C:\Vetrivel\winforms.png";
        var memory = new MemoryStream();
        using (var stream = new FileStream(path, FileMode.Open))
        {
            await stream.CopyToAsync(memory);
        }
        memory.Position = 0;
        var ext = Path.GetExtension(path).ToLowerInvariant();
        return File(memory, GetMimeTypes()[ext], Path.GetFileName(path));
    }

    private Dictionary<string, string> GetMimeTypes()
    {
        return new Dictionary<string, string>
        {
            {".txt", "text/plain"},
            {".pdf", "application/pdf"},
            {".doc", "application/vnd.ms-word"},
            {".docx", "application/vnd.ms-word"},
            {".png", "image/png"},
            {".jpg", "image/jpeg"},
            ...
        };
    }
}
    [HttpGet]
    public async Task<FileStreamResult> Download(string url, string name, string contentType)
    {
        var stream = await new HttpClient().GetStreamAsync(url);

        return new FileStreamResult(stream, contentType)
        {
            FileDownloadName = name,
        };
    }

我的方式很短,我認為它適合大多數人的需要。

  [HttpPost]
  public ActionResult Download(string filePath, string fileName)
  {
      var fileBytes = System.IO.File.ReadAllBytes(filePath);
      new FileExtensionContentTypeProvider().TryGetContentType(Path.GetFileName(filePath), out var contentType);
      return File(fileBytes, contentType ?? "application/octet-stream", fileName);
  }

這對我有用:

 httpContext.Response.Headers.Append("content-disposition", "attachment;filename=" + mytextfilename);            
 httpContext.Response.ContentType = "application/text";
 httpContext.Response.WriteAsync(mytextfile);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM