web-dev-qa-db-ja.com

WebAPI ASP.NET CoreからExcelファイルを返す方法

同様の質問で、このコードを使用してPDFをダウンロードします。

Controllerフォルダー内のローカルファイル(.xlsx、.pdf、.Zip)でテストしています。

同様の質問はこちら

[HttpGet("downloadPDF")]
public FileResult TestDownloadPCF()
{
   HttpContext.Response.ContentType = "application/pdf";
   FileContentResult result = new FileContentResult
   (System.IO.File.ReadAllBytes("Controllers/test.pdf"), "application/pdf")
    {
      FileDownloadName = "test.pdf"
    };
   return result;
}

This works great!

ただし、Excelファイル(.xlsx)またはZipファイル(.Zip)などの別のファイルの場合、テストは正しく機能しません。

コード:

[HttpGet("downloadOtherFile")]
public FileResult TestDownloadOtherFile()
{
  HttpContext.Response.ContentType = 
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
  FileContentResult result = new FileContentResult(System.IO.File.ReadAllBytes("Controllers/test.xlsx"), 
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  {
    FileDownloadName = "otherfile"
   };
  return result;
}

結果: enter image description here

また、次のContent-Typeでテストを行いました。

  • 「アプリケーション/vnd.ms-Excel」
  • 「アプリケーション/vnd.ms-Excel.12」

同じ結果を得る。

ファイルの種類を返す正しい方法はどれですか?

あなたの答えをありがとう

私の(実用的な)ソリューション:

  • EPPlus.Core。を使用してXLSXファイルを動的に作成するクラスがあります。
    • これは、生成されたファイルのパスのFileInfoを返します。

これは私のコントローラーにあるものです:

[HttpGet("test")]
public async Task<FileResult> Get()
{
    var contentRootPath = _hostingEnvironment.ContentRootPath;

    // "items" is a List<T> of DataObjects
    var items = await _mediator.Send(new GetExcelRequest());

    var fileInfo = new ExcelFileCreator(contentRootPath).Execute(items);
    var bytes = System.IO.File.ReadAllBytes(fileInfo.FullName);

    const string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    HttpContext.Response.ContentType = contentType;
    HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");

    var fileContentResult = new FileContentResult(bytes, contentType)
    {
        FileDownloadName = fileInfo.Name
    };

    return fileContentResult;
}

そして、これがAngular2にあるものです:

downloadFile() {
    debugger;
    var headers = new Headers();
    headers.append('responseType', 'arraybuffer');

    let url = new URL('api/excelFile/test', environment.apiUrl);

    return this.http
        .get(url.href, {
            withCredentials: true,
            responseType: ResponseContentType.ArrayBuffer
        })
        .subscribe((response) => {
            let file = new Blob([response.blob()], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
            let fileName = response.headers.get('Content-Disposition').split(';')[1].trim().split('=')[1];
            saveAs(file, fileName);
        },
        err => this.errorHandler.onError(err)
        );
}
6
BCdotWEB

私も同じ問題を抱えていました。私の問題はクライアントのリクエストが原因でしたが、サーバーの応答ではありません。 Getリクエストのヘッダーオプションにレスポンスコンテンツタイプを追加することで解決しました。 Angular 2。

クライアントからのリクエスト(Angular 2)** filesaver.jsライブラリが必要

this._body = '';

    let rt: ResponseContentType = 2; // This is what I had to add ResponseContentType (2 = ArrayBuffer , Blob = 3)
        options.responseType = rt;
    if (url.substring(0, 4) !== 'http') {
        url = config.getApiUrl(url);
    }

    this.http.get(url, options).subscribe(
        (response: any) => {
            let mediaType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
            let blob = new Blob([response._body], { type: mediaType });
            let filename = 'test.xlsx';
            fileSaver.saveAs(blob, filename);
        });

サーバーサイドコード。 (.netコア)

    [HttpGet("{dataViewId}")]
    public IActionResult GetData(string dataViewId)
    {
        var fileName = $"test.xlsx";
        var filepath = $"controllers/test/{fileName}";
        var mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        byte[] fileBytes = System.IO.File.ReadAllBytes(filepath);
        return File(fileBytes, mimeType, fileName);
    }

ご覧になりたい方はこちらをご覧ください。

AngularJsアプリでのダウンロードの破損

C#ファイルのダウンロードが破損しています

3
Jay Culpepper

次に、ファイルをダウンロードする方法の例を示します。その後、Excelファイルをダウンロードするシナリオをモデル化できます。

public IActionResult Index([FromServices] IHostingEnvironment hostingEnvironment)
{
    var path = Path.Combine(hostingEnvironment.ContentRootPath, "Controllers", "TextFile.txt");
    return File(System.IO.File.OpenRead(path), contentType: "text/plain; charset=utf-8", fileDownloadName: "Readme.txt");
}

ファイルがwwwrootフォルダーにある場合は、代わりに以下のようなことを行うことができます。

public IActionResult Index()
{
    return File(virtualPath: "~/TextFile.txt", contentType: "text/plain; charset=utf-8", fileDownloadName: "Readme.txt");
}
1
Kiran Challa