简体   繁体   English

如何使用 ServiceStack 和 Angular 下载动态生成的 XML 文件?

[英]How to download a dynamically generated XML file with ServiceStack and Angular?

The following code works in theory, but it lacks error handling.以下代码在理论上有效,但它缺乏错误处理。 The problem I have is that it starts downloading the XML file when a new window opens with the url created by the service stack.我遇到的问题是,当使用服务堆栈创建的 url 打开新的 window 时,它开始下载 XML 文件。 But now when an error occurs server side, you are on this new page with only the stack trace.但是现在当服务器端发生错误时,您在这个新页面上只有堆栈跟踪。

What is the right way to download a dynamic binary (not stored on disk) with service stack and Angular?使用服务堆栈和 Angular 下载动态二进制文件(未存储在磁盘上)的正确方法是什么?

Angular with ServiceStack: Angular 与 ServiceStack:

downloadExportXML(){
  const request = new GetRatingsExportRequest(this.request);
  const url = this.jsonServiceClient.createUrlFromDto("GET", request)
  window.open(url);
}

WebAPI (C#) to collect the XML File. WebAPI (C#) 收集 XML 文件。

  public HttpResult Get(GetRatingsExportRequest request)
  {
      MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlContent));
      var result = new HttpResult(ms.ToArray());
      var disposition = $"attachment;filename=myfilename;";
      result.Headers.Add(HttpHeaders.ContentDisposition, disposition);
      return result;
  }

If you return the content with a Content-Disposition: attachment HTTP Header the browser will treat it as a separate File Download.如果您返回带有Content-Disposition: attachment HTTP Header 浏览器会将其视为单独的文件下载。

If you don't want that return it as a normal XML Response.如果您不希望将其作为正常的 XML 响应返回。 But the way you're returning it is fairly inefficient, ie calling ToArray() defeats the purpose of using a Stream since you've forced loaded the entire contents of the Stream in memory, instead you should just return the stream so it gets asynchronously written to the HTTP Response as a Stream, eg: But the way you're returning it is fairly inefficient, ie calling ToArray() defeats the purpose of using a Stream since you've forced loaded the entire contents of the Stream in memory, instead you should just return the stream so it gets asynchronously写入 HTTP 响应为 Stream,例如:

return new HttpResult(ms, MimeTypes.Xml);

But if you've already got the XML as a string you don't need the overhead of the MemoryStream wrapper either and can just return the XML string as-is, eg:但是,如果您已经将 XML 作为字符串获得,则您也不需要MemoryStream包装器的开销,并且可以按原样返回 XML 字符串,例如:

return new HttpResult(xmlContent, MimeTypes.Xml);

I couldnt make it work.我无法让它工作。 So i created this workaround: Generating the URL to download the XML with the ServiceStack method jsonServiceClient.createUrlFromDto() and than downloading the file via Angular HTTPClient.所以我创建了这个解决方法:生成 URL 以使用 ServiceStack 方法jsonServiceClient.createUrlFromDto()下载 XML,然后通过 ZC31C335EF37213C451B18BA0DD3 HTTPClient.DE 下载文件

downloadExportXML(){
  const request = new GetRatingsExportRequest(this.request);
  const url = this.jsonServiceClient.createUrlFromDto("GET", request)

  this.httpClient.get(url, {observe: 'response', responseType: 'arraybuffer'})
    .subscribe((response) => {
      var contentDisposition = response.headers.get('content-disposition');
      this.downloadFile(response.body)
    },
    error => this.handleError()
  );
}

private downloadFile(blobData: ArrayBuffer)
{
    let file = new Blob([blobData], { type: 'application/binary' });
    let fileURL = URL.createObjectURL(file);
    let fileLink = document.createElement('a');
    fileLink.href = fileURL;
    fileLink.download = "MYFILENAME.pdf";
    fileLink.click();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM