Angular download file after POST request

时间:2017-10-30 15:31:26

标签: c# asp.net-mvc angular typescript asp.net-core

I have several export routes on an asp.net core application, but all of them are accessed by a GET request, eg: /api/{projectid}/{parameter}

These requests are generating xlsx files and sending them to the client. Now I have a similar request but I have to pass a long array to the method, so I would like to make it into a POST method and send the array (and other parameters) in the http body.

I get the correct response from the server (an array buffer starting with PK...) but I can't tell angular to save it as a file as I did with the similar GET requests. If I rewrite this back to start a GET request it works fine. What am I doing wrong?

Controller method:

[HttpPost("[action]")]
public IActionResult Export([FromBody] DistributionExportPostModel model)
{
    var project = _ctx.Projects.FirstOrDefault(x=>x.Id == model.ProjectId);
    byte[] xlsx = createXlsxFile(project, model.Selection, model.ComparisonBase);
    var mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    var fileName = $"TaskExport-"+project.Name+"-"+DateTime.Now.ToString("yyyyMMddHHmmss")+".xlsx";

    return File(xlsx, mimeType, fileName);
}   

Angular provider method:

export(projectid:string, selection:string[], comparisonBase:string):Promise<any[]> {
        //let headers:Headers = new Headers();
        //headers.append('Accept', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');

        //let params: URLSearchParams = new URLSearchParams();

        let requestOptions = new RequestOptions();
        requestOptions.responseType = ResponseContentType.ArrayBuffer;
        return new Promise<any[]>((resolve) =>
            this.http.post('/api/Distribution/Export', {
                //'+projectid+'/'+comparisonBase+'/'+selection.join(','),
                'ProjectId': projectid,
                'Selection': selection,
                'ComparisonBase': comparisonBase
            }, requestOptions).subscribe((res) => {
                window.open(res.url, '_blank');
                resolve();
            })
        );
    }    

1 个答案:

答案 0 :(得分:1)

以下内容适用于Chrome。

var blob = new Blob(yourData, {type: "octet/stream"});
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = name;
a.click();
window.URL.revokeObjectURL(url);

对于IE和Firefox,试试这个:

window.navigator.msSaveBlob(blob, filename);

在点击之前,您可能需要将锚添加到DOM。