Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/30.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular2从Web API下载excel文件,文件已损坏_Angular - Fatal编程技术网

Angular2从Web API下载excel文件,文件已损坏

Angular2从Web API下载excel文件,文件已损坏,angular,Angular,我正在尝试下载一个用ClosedXML创建的文件。我已经验证了该文件没有损坏,但出于某种原因,它只适用于Angular1,而不是Angular2。返回文件的web api代码为: HttpResponseMessage response = new HttpResponseMessage(); response.StatusCode = HttpStatusCode.OK; response.Content = new ByteArrayContent(ms.GetBuffer()); resp

我正在尝试下载一个用ClosedXML创建的文件。我已经验证了该文件没有损坏,但出于某种原因,它只适用于Angular1,而不是Angular2。返回文件的web api代码为:

HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
response.Content = new ByteArrayContent(ms.GetBuffer());
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
return response;
在Angular2中,在我的web服务中:

let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('responseType', 'arrayBuffer');
this.observableDataGet = this._http.post(`${AppSettings.REPORTS_API_URL}/Report/MonthlySpreadsheet`, {headers: this.getHeaders()})
    .map(response => {
        if (response.status == 400) {
            return "FAILURE";
        } else if (response.status == 200) {
            var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
            var blob = new Blob([response.arrayBuffer()], { type: contentType });
            return blob;
        }
    })
在我的组件中:

.subscribe(blob => {
    var downloadUrl= URL.createObjectURL(blob);
    window.open(downloadUrl);
},
文件已下载,但当我尝试访问它时,它已损坏,并且使用Angular1下载时,其大小是文件的两倍

如果我使用Angular1调用相同的API,则可以很好地下载该文件

我的服务代码:

function generateMonthlySpreadsheet(header) {
    var request = $http({
        method: "post",
        responseType: 'arraybuffer',
        url: TEST_API_URL + 'Report/MonthlySpreadsheet',
        timeout: 30000,
        headers: header
    });
    return ( request.then(handleSuccess, handleError) );
}
其中handleSuccess返回response.data(对于angular2,我无法获取该数据)

以及调用服务的代码:

alertAppService.generateMonthlySpreadsheet(header).then(function (data){
    var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
    var objectUrl = URL.createObjectURL(blob);
    window.open(objectUrl);
有趣的是,在Angular2中,如果我简单地将我的Web服务更改为GET(但是我想要POST,但只是想尝试一下),然后去掉服务代码并简单地进行此调用,那么文件就可以了:

window.open(`${AppSettings.REPORTS_API_URL}/Report/MonthlySpreadsheet`, "_blank");
那么,真的,这里的区别是什么?为什么相同或非常相似的代码适用于Angular1而不适用于Angular2


--凯伦

我知道其他人也发现了同样的问题。我已经解决了这个问题,但必须切换到xhr才能使其正常工作

第一种方法不起作用。我从上面把它简化了一些:

    generateMonthlySpreadsheet2(searchCriteria: Object) {
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        headers.append('responseType', 'blob');

        return this._http.post(`${AppSettings.REPORTS_API_URL}/Report/MonthlySpreadsheet`, {headers: headers})
            .map(response => {
                if (response.status == 400) {
                    this.handleError;
                } else if (response.status == 200) {
                    var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
                    var blob = new Blob([(<any>response)._body], { type: contentType });            // size is 89KB instead of 52KB
//                    var blob = new Blob([(<any>response).arrayBuffer()], { type: contentType });  // size is 98KB instead of 52KB
//                    var blob = new Blob([(<any>response).blob()], { type: contentType });         // received Error: The request body isn't either a blob or an array buffer
                    return blob;
                }
            })
            .catch(this.handleError);
    }
generateMonthlySpreadsheet2(搜索条件:对象){
let headers=新的headers();
headers.append('Content-Type','application/json');
append('responseType','blob');
返回此内容。_http.post(`${AppSettings.REPORTS\u API\u URL}/Report/MonthlySpreadsheet`,{headers:headers})
.map(响应=>{
如果(response.status==400){
这是handleError;
}否则如果(response.status==200){
var contentType='application/vnd.openxmlformats of icedocument.spreadsheetml.sheet';
var blob=new blob([(响应)。_body],{type:contentType});//大小是89KB,而不是52KB
//var blob=new blob([(response).arrayBuffer(),{type:contentType});//大小为98KB,而不是52KB
//var blob=new blob([(response).blob()],{type:contentType});//收到错误:请求正文不是blob或数组缓冲区
返回斑点;
}
})
.接住(这个.把手错误);
}
第二种方法确实有效:

generateMonthlySpreadsheet(searchCriteria: Object): Observable<Object[]> {
    return Observable.create(observer => {

        let xhr = new XMLHttpRequest();

        xhr.open('POST', `${AppSettings.REPORTS_API_URL}/Report/MonthlySpreadsheet`, true);
        xhr.setRequestHeader('Content-type', 'application/json');
        xhr.responseType='blob';

        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {

                    var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
                    var blob = new Blob([xhr.response], { type: contentType });
                    observer.next(blob);
                    observer.complete();
                } else {
                    observer.error(xhr.response);
                }
            }
        }
        xhr.send();

    });
}
generateMonthlySpreadsheet(搜索条件:对象):可观察{
返回可观察的。创建(观察者=>{
设xhr=newXMLHttpRequest();
open('POST',`${AppSettings.REPORTS\u API\u URL}/Report/MonthlySpreadsheet',true);
setRequestHeader('Content-type','application/json');
xhr.responseType='blob';
xhr.onreadystatechange=函数(){
if(xhr.readyState==4){
如果(xhr.status==200){
var contentType='application/vnd.openxmlformats of icedocument.spreadsheetml.sheet';
var blob=新blob([xhr.response],{type:contentType});
观察员:下一个(blob);
observer.complete();
}否则{
观察者错误(xhr响应);
}
}
}
xhr.send();
});
}
希望这能帮助别人!我在别处看到了这个问题,所以我也会在那里添加我的解决方案的链接

--Karen

这对我来说很有效(请确保服务确实将xlsx文件作为响应发送回):

  • 为显示“保存文件”弹出窗口安装这些依赖项

  • 在您的服务中导入:

    import * as FileSaver from 'file-saver';
    
  • 用法:

    downloadFile(): void {
        let url: string = “http://yourdomain.com/exports/excelExport.aspx”;
       let headers = new Headers({ 'Content-Type': 'application/json'} );
    
        //in case you have custom headers, else you can ignore this part
    headers.set('x-custom-header1', “some value”);
        headers.set('x-custom-header2', “some value2”);
    
        let options = new RequestOptions({responseType: ResponseContentType.Blob, headers });
    
        this.http.get(url, options)
            .map(res => res.blob())
            .subscribe(
            data => {
    FileSaver.saveAs(data, 'Export.xlsx'); 
            },
            err => {
                console.log('error');
                console.error(err);
            });
    }
    

  • 这是我用来用样式(颜色..)加载完整文件的解决方案

    WebApi:

     [HttpGet]
            [Route("api/RapproResult/DownloadExcelReport/{reportName}")]
            public HttpResponseMessage DownloadExcelReport( string reportName)
            {
    
    
                try
                {
                     string filePath = HttpContext.Current.Server.MapPath("~/Report/Report_TEST.XLS");
    
                    if (!string.IsNullOrEmpty(filePath ))
                    {
    
    
                        using (MemoryStream ms = new MemoryStream())
                        {
                            using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                            {
                                byte[] bytes = new byte[file.Length];
                                file.Read(bytes, 0, (int)file.Length);
                                ms.Write(bytes, 0, (int)file.Length);
    
                                HttpResponseMessage httpResponseMessage = new HttpResponseMessage(); 
                                httpResponseMessage.Content = new ByteArrayContent(ms.GetBuffer());
                                httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                                httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    
                                httpResponseMessage.StatusCode = HttpStatusCode.OK;
                                return httpResponseMessage;
                            }
                        }
                    }
                    return this.Request.CreateResponse(HttpStatusCode.NotFound, "File not found.");
                }
                catch (Exception ex)
                {
                    return   this.Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
                }
    
    
            }
    
    这是角度服务:

     protected downloadExcelReportService( reportName: string) {
    
            let completeUrl = this.downloadExcelReportUrl+reportName;
            return Observable.create(observer => {
                let xhr = new XMLHttpRequest();
    
                xhr.open('GET', completeUrl, true);
                xhr.setRequestHeader('Content-type', 'application/json');
                xhr.responseType='blob';
    
                xhr.onreadystatechange = function () {
                  if (xhr.readyState === 4) {
                    if (xhr.status === 200) { 
                        debugger;
                      var contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
                      var blob = new Blob([xhr.response], { type: contentType });
                      observer.next(blob);
                      observer.complete();
                      return observer;
    
                    } else {
                      observer.error(xhr.response);
                    }
                  }
                }
                debugger;
                xhr.send();
              });
        }
    
    最后是使用FileSaverAPI的角度组件方法

    import * as FileSaver from "file-saver";
    
    
    
     downloadexcelReport(data)
          { 
              this._servive.downloadExcelReport(data.RapproName)
              .subscribe(
                _data =>  FileSaver.saveAs(_data, data.RapproName+".xls" ) ), 
                error => console.log("Error downloading the file."),
                () => console.log('Completed file download.');  
          }
    
    我希望这对你有帮助

    Latest solution Try If using Angular 5:
    
    ///angular side
    
    //header
    let expheaders = new Headers({ 'Content-Type': 'application/json', 'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    let options = new RequestOptions({ headers: expheaders, responseType: ResponseContentType.Blob });
    
    
    this.http.post(this.modeleffectiveperiodserviceurl+"ExportToXlsx",JSON.stringify({
                               modeleffectiveperioddetails:model,
                               colheader:columns
                               }),options)
                               .subscribe(data => { 
                                 var blob = new Blob([data.blob()], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
                                 var url= window.URL.createObjectURL(blob);
                                 window.open(url);                   
                              });
    
    
    
    //////////server side
    
    
      byte[] bytes = this._exportmanager.GetExcelFromServer(modeleffectivepc, colheader);
                HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
                httpResponseMessage.Content = new ByteArrayContent(bytes.ToArray());
                httpResponseMessage.Content.Headers.Add("x-filename", fileName);
                httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
                httpResponseMessage.StatusCode = HttpStatusCode.OK;
                return httpResponseMessage;
    
    please tell if any problem
    
    Latest solution Try If using Angular 5:
    
    ///angular side
    
    //header
    let expheaders = new Headers({ 'Content-Type': 'application/json', 'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    let options = new RequestOptions({ headers: expheaders, responseType: ResponseContentType.Blob });
    
    
    this.http.post(this.modeleffectiveperiodserviceurl+"ExportToXlsx",JSON.stringify({
                               modeleffectiveperioddetails:model,
                               colheader:columns
                               }),options)
                               .subscribe(data => { 
                                 var blob = new Blob([data.blob()], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
                                 var url= window.URL.createObjectURL(blob);
                                 window.open(url);                   
                              });
    
    
    
    //////////server side
    
    
      byte[] bytes = this._exportmanager.GetExcelFromServer(modeleffectivepc, colheader);
                HttpResponseMessage httpResponseMessage = new HttpResponseMessage();
                httpResponseMessage.Content = new ByteArrayContent(bytes.ToArray());
                httpResponseMessage.Content.Headers.Add("x-filename", fileName);
                httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
                httpResponseMessage.StatusCode = HttpStatusCode.OK;
                return httpResponseMessage;
    
    please tell if any problem