繁体   English   中英

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

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

我在服务器上有一个文件要发送给客户端:

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

我也试过

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

在客户端,我接受使用:

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));
        })
}

客户端收到的文件已损坏且无法打开。 服务器上的文件很好,可以完美打开。 结果文件还是打不开,甚至重了2倍(服务器上487 KB,客户端925 KB)。

您可以使用文件结果并只提供一个将返回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"
       };
}

现在您只需要提供链接,浏览器就会知道如何处理它。 那就不用自己动手了。

编辑:我刚刚用 angular 测试了这种方法,在使用 angulars HttpClient时,您需要执行以下操作来下载文件。

首先,您需要通过 npm 安装文件保护程序。

npm i --save file-saver

然后在您的模块中导入并包含 HttpClientModule

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

现在继续为您服务并执行以下操作

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
       });
    });
}

然后处理 blob 并创建一个文件保存对话框。

我不知道为什么问题中指定的选项不起作用。 但我找到了一个解决方案,可以说“在另一个森林中”。 我不是很精通,所以我只描述解决问题的过程。 一开始,我会立即说问题出在客户端。 服务器上的方法从一开始就正常工作。 我决定使用另一种方法来下载文件“获取”。 并在论坛中找到了下一个帖子。 从那里我得到了以下答案

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);
    });

他也没有为我工作。 我这样改了

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

因为这条线什么也没发生

URL.revokeObjectURL(url);

此选项有效,但被搞砸了。 他用一个奇怪的名字保存了这个文件,没有扩展名。 然后我就这样改了。

    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);
            });

它有效! 我为英语道歉。 我正在使用谷歌翻译

要下载任何文件,首先安装以下,

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

在你的组件中包含这些包(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';

前端代码,

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

角度代码,

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 代码,

        [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