Mam plik na serwerze, który chcę wysłać do klienta:

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

Próbowałem też z

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

Na kliencie akceptuję użycie:

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

Plik, który odbiera klient jest uszkodzony i nie otwiera się. Plik, który jest na serwerze jest w porządku i doskonale się otwiera. Powstały plik nadal nie otwiera, a nawet waży 2 razy więcej (na serwerze 487 KB, a klient ma 925 KB).

4
Жуэль Итуа 19 luty 2018, 13:51

3 odpowiedzi

Najlepsza odpowiedź

Nie wiem, dlaczego opcja określona w pytaniu nie działa. Ale znalazłem rozwiązanie, więc powiedzieć "w innym lesie". Nie jestem bardzo zorientowany, więc po prostu opiszę proces rozwiązania problemu. Na początku natychmiast powiem, że problem był po stronie klienta. Metoda na serwerze działa poprawnie od początku. Postanowiłem użyć innej metody, aby pobrać pliki "Fetch". I przyszedł na następny post w forum. Stamtąd wziąłem następującą odpowiedź

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

Nie działał też dla mnie. Tak zmieniłem

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

Z powodu tej linii nic się nie stało

URL.revokeObjectURL(url);

Ta opcja działała, ale z przykręconym. Zapisał plik z dziwną nazwą i bez rozszerzenia. Wtedy to zmieniłem.

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

I to działa! Przepraszam za angielski. Używam tłumacza Google

4
Жуэль Итуа 25 luty 2018, 17:02

Możesz użyć wyniku plików i po prostu podaj link API, który zwróci FileContentreult.

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

Teraz musisz tylko podać link i przeglądarka będzie wiedziała, jak sobie z tym poradzić. Nie musisz tego robić tego sam.

Edytuj: Właśnie przetestowałem to podejście z kątem, musisz wykonać następujące czynności, aby pobrać plik podczas korzystania z kątów httpclient.

Najpierw musisz zainstalować oszczędność plików przez NPM.

npm i --save file-saver

Następnie w imporcie modułu i zawierać httpclientmodule

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

Teraz przejdź do swojej usługi i wykonaj następujące czynności

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

Następnie BLOB jest obsługiwany, a tworzony jest okno dialogowe Zapisywanie plików.

8
Stanley Mohlala 17 lipiec 2019, 12:06

Aby pobrać dowolny plik, najpierw zainstaluj następujące elementy

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

Dołącz te pakiety w komponencie (kąt 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';

Kod frontowy,

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

Kątowy kod,

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

Kod API CORE .NET,

        [HttpGet]
        public async Task<FileStream> DownloadFile(string fileName)
        {
            return new FileStream(file, FileMode.Open, FileAccess.Read);
        }
0
Bharathkumar V 13 listopad 2019, 09:07