简体   繁体   English

如何从 ASP.NET Core 正确下载文件到 Angular?

[英]How to correctly download files to Angular from ASP.NET Core?

I have a file on the server that I want to send to the client:我在服务器上有一个文件要发送给客户端:

[HttpPost]
public IActionResult Test()
{
    byte[] bytes = System.IO.File.ReadAllBytes(Path.Combine(FilesFolder, "test.docx"));
    return File(bytes, _contentTypeWord);
}

I also tried with我也试过

return PhysicalFile(pathUploadFile, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");

At the client I accept using:在客户端,我接受使用:

private _downloadFile(data: ArrayBuffer, fileName: string, contentType: string) {
    var blob = new Blob([data], { type: contentType });
    var url = window.URL.createObjectURL(blob);

    var link = document.createElement("a");
    link.setAttribute("href", url);
    link.setAttribute("download", fileName);
    link.style.display = "none";
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}

public test() {
    this.http.post("Diplom/Test", { }, {
        headers: this.headers(),
    }).subscribe(
        result => {
            this._downloadFile(result.arrayBuffer(), "test.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
        },
        error => {
            alert("Не удалось отредактировать файл");
            console.error(JSON.stringify(error));
        })
}

The file that the client receives is corrupt and does not open.客户端收到的文件已损坏且无法打开。 The file that is on the server is fine and opens perfectly.服务器上的文件很好,可以完美打开。 The resulting file still does not open, and even weighs 2 times more (on the server 487 KB, and the client has 925 KB).结果文件还是打不开,甚至重了2倍(服务器上487 KB,客户端925 KB)。

You can use a file result and just provide an api link that will return a FileContentResult .您可以使用文件结果并只提供一个将返回FileContentResult的 api 链接。

public IActionResult Download(// some parameter) 
{
   // get the file and convert it into a bytearray
   var locatedFile = ....
   return new FileContentResult(locatedFile, new 
       MediaTypeHeaderValue("application/octet"))
       {
           FileDownloadName = "SomeFileDownloadName.someExtensions"
       };
}

Now you only need to provide the link and browser will know how to handle it.现在您只需要提供链接,浏览器就会知道如何处理它。 No need to do it yourself then.那就不用自己动手了。

Edit: I just tested this approach with angular, you need to do the following to download the file when using angulars HttpClient .编辑:我刚刚用 angular 测试了这种方法,在使用 angulars HttpClient时,您需要执行以下操作来下载文件。

First you need to install file-saver via npm.首先,您需要通过 npm 安装文件保护程序。

npm i --save file-saver

Then in your module import and include HttpClientModule然后在您的模块中导入并包含 HttpClientModule

import { HttpClientModule } from '@angular/common/http';
...
@NgModule({
   imports: [
      HttpClientModule
      ...
   ]
...
})

Now go ahead to your service and do the following现在继续为您服务并执行以下操作

import { HttpClient } from '@angular/common/http';
import { saveAs } from 'file-saver';

@Injectable()
export class MyFileService {

   public constructor(private http: HttpClient) {}

       public downloadFile() {
    this.http.get('my-api-url', { responseType: 'blob' }).subscribe(blob => {
       saveAs(blob, 'SomeFileDownloadName.someExtensions', {
          type: 'text/plain;charset=windows-1252' // --> or whatever you need here
       });
    });
}

Then blob is handled and a file-save dialog is created.然后处理 blob 并创建一个文件保存对话框。

I do not know why the option specified in the question does not work.我不知道为什么问题中指定的选项不起作用。 But I found a solution, so to say "in another forest".但我找到了一个解决方案,可以说“在另一个森林中”。 I'm not very versed, so I'll just describe the process of solving the problem.我不是很精通,所以我只描述解决问题的过程。 For the beginning I will immediately say that the problem was on the client's side.一开始,我会立即说问题出在客户端。 The method on the server worked correctly from the start.服务器上的方法从一开始就正常工作。 I decided to use another method to download the files "fetch".我决定使用另一种方法来下载文件“获取”。 And came across the next post in the forum .并在论坛中找到了下一个帖子。 From there I took the following answer从那里我得到了以下答案

this.httpClient
    .fetch(url, {method, body, headers})
    .then(response => response.blob())
    .then(blob => URL.createObjectURL(blob))
    .then(url => {
        window.open(url, '_blank');
        URL.revokeObjectURL(url);
    });

He did not work for me either.他也没有为我工作。 I changed it so我这样改了

    fetch(url, {
            method: 'POST',
            headers: this.headers()
        })
        .then(response => response.blob())
        .then(blob => URL.createObjectURL(blob))
        .then(url => {
            window.open(url, '_blank');
        });

Because of this line nothing happened因为这条线什么也没发生

URL.revokeObjectURL(url);

This option worked, but with screwed.此选项有效,但被搞砸了。 He saved the file with a strange name and no extension.他用一个奇怪的名字保存了这个文件,没有扩展名。 Then I changed it so.然后我就这样改了。

    fetch(url, {
            method: 'POST',
            headers: this.headers()
        })
            .then(response => response.blob())
            .then(blob => URL.createObjectURL(blob))
            .then(url => {
                var link = document.createElement("a");
                link.setAttribute("href", url);
                link.setAttribute("download", "test.docx");
                link.style.display = "none";
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            });

And it works!它有效! I apologize for the English.我为英语道歉。 I'm using Google translator我正在使用谷歌翻译

To download any file, first install the following,要下载任何文件,首先安装以下,

npm install rxjs --save
npm install file-saver --save

Include these packages in your component(Angular 2+),在你的组件中包含这些包(Angular 2+),

import { Observable } from 'rxjs';
import { saveAs } from 'file-saver';
import { map } from "rxjs/operators";
import { Subject } from 'rxjs';
import { HttpEventType, HttpClient } from '@angular/common/http';

Front-end code,前端代码,

<input type="button" placeholder="Download" value="Download" (click)="download(file)" />

Angular Code,角度代码,

download(file) {
        let fileName = file;
        let checkFileType = fileName.split('.').pop();
        var fileType;
        if (checkFileType == ".txt") {
            fileType = "text/plain";
        }
        if (checkFileType == ".pdf") {
            fileType = "application/pdf";
        }
        if (checkFileType == ".doc") {
            fileType = "application/vnd.ms-word";
        }
        if (checkFileType == ".docx") {
            fileType = "application/vnd.ms-word";
        }
        if (checkFileType == ".xls") {
            fileType = "application/vnd.ms-excel";
        }
        if (checkFileType == ".png") {
            fileType = "image/png";
        }
        if (checkFileType == ".jpg") {
            fileType = "image/jpeg";
        }
        if (checkFileType == ".jpeg") {
            fileType = "image/jpeg";
        }
        if (checkFileType == ".gif") {
            fileType = "image/gif";
        }
        if (checkFileType == ".csv") {
            fileType = "text/csv";
        }
        this.DownloadFile(fileName, fileType)
            .subscribe(
                success => {
                    saveAs(success, fileName);
                },
                err => {
                    alert("Server error while downloading file.");
                }
            );
    }

    DownloadFile(filePath: string, fileType: string): Observable<any> {

        let fileExtension = fileType;
        let input = filePath;

        return this.http.get(this.yourApiUrl + "?fileName=" + input, {
            responseType: 'blob',
            observe: 'response'
        })
            .pipe(
                map((res: any) => {
                    return new Blob([res.body], { type: fileExtension });
                })
            );
    }

.NET Core API code, .NET Core API 代码,

        [HttpGet]
        public async Task<FileStream> DownloadFile(string fileName)
        {
            return new FileStream(file, FileMode.Open, FileAccess.Read);
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM