Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
186 views
in Technique[技术] by (71.8m points)

c# - 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).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use a file result and just provide an api link that will return a FileContentResult.

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.

First you need to install file-saver via npm.

npm i --save file-saver

Then in your module import and include 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...