【问题标题】:Making a POST request that returns a PDF using Angular's HttpClient使用 Angular 的 HttpClient 发出返回 PDF 的 POST 请求
【发布时间】:2018-12-11 19:33:41
【问题描述】:

我正在使用返回 PDF 作为响应的 Web API 服务 (DocRaptor)。在最初使用 API 时,我能够生成 PDF 并在他们的网站上查看 PDF。我收到一个 200 状态代码,告诉我响应成功。但是,使用此代码,帖子的结果仍然在 Angular 端作为错误返回:

    return this.http
  .post("https://docraptor.com/docs", {
    headers: {
      "Content-Type": "application/json"
    },
    user_credentials: "WEB_API_KEY",
    doc: {
      test: true,
      name: "testDocument.pdf",
      document_content: documentContent,
      type: "pdf"
    }
  })
  .subscribe(
    res => {
      console.log(res);
    },
    err => {
      console.log("Error occured: " + err);
    }
  );

我假设这是因为代码期望 JSON 作为结果,而 API 返回了 PDF。

Angular 在Requesting non-JSON Data 上的文档没有详细说明如何使用 HttpClient 来使用响应(DocRaptor 的文档也没有就此问题)。调试时,我无法告诉(使用 Chrome 中的网络选项卡)API 调用甚至正在发送,或者使用下面的代码返回响应。这可能是以下语法中的一个问题,但以下代码是我尝试使用我知道可用的文档的一种方法:

   return this.http
  .post("https://docraptor.com/docs", {
    responseType: "blob",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/pdf"
    },
    user_credentials: "WEB_API_KEY",
    doc: {
      test: true,
      name: "testDocument.pdf",
      document_content: documentContent,
      type: "pdf"
    }
  })
  .pipe(tap(data => this.downloadFile(data, "application/pdf")));

更新:

我已按照此处回复中的建议重新构建了我的代码。但是,我仍然收到原始错误,即我从 DocRaptor API 返回 200 状态,但 Angular 的 HttpClient 没有将响应解析为 PDF。我已在标题中添加以接受 PDF,但我仍然收到一条错误消息“位置 0 处的 JSON 中的意外令牌 %”。

repl.component.ts

  generatePdf() {
    var htmlCard = this.cards.filter((card: Card) => card.language === "html")[0];
    var cssCard = this.cards.filter((card: Card) => card.language === "css")[0];

    var documentContent = this.generateCode(
      htmlCard.editorContent,
      cssCard.editorContent
    );

    this.docRaptorService.generatePdf(documentContent).subscribe(results => {
      let blob = results;
      let filename = "testDocument.pdf";
      FileSaver.saveAs(blob, filename);
    });
  }

doc-raptor.service.ts

  generatePdf(documentContent: string) {
    return this.http
      .post("https://docraptor.com/docs", {
        headers: {
          "Content-Type": "application/json",
          Accept: "application/pdf"
        },
        user_credentials: "WEB_API_KEY",
        doc: {
          test: true,
          name: "testDocument.pdf",
          document_content: documentContent,
          type: "pdf"
        },
        responseType: "blob"
      })
      .pipe(
        tap(
          data => console.log(documentContent, data),
          error => console.log(documentContent, error)
        )
      );
  }

【问题讨论】:

  • 在您的第二个示例中,未订阅 Observable。不知道你是否在其他地方订阅,但 Observables 在订阅之前什么都不做。
  • 我不确定pipetapsubscribe 的关系如何。 Angular 的文档在本节中省略了 subscribe,因此我假设当您尝试在返回中使用非 JSON 数据时,使用 pipetap 代替 subscribe
  • pipetap 是运算符,是 Observable 流的核心部分。当数据通过流时,它们会更改数据,在这种情况下,将数据散布到对象中。 Angular 在这里省略了subscribe,因为在服务中将subscribe 转换为Observables 被认为是不好的做法,而是将Observable 返回给调用者。 Observables 仅在订阅时运行。
  • 以下链接解决了我的问题。stackoverflow.com/questions/50332447/…

标签: angular pdf http-post pdf-generation angular-httpclient


【解决方案1】:
 .pipe(tap(data => this.downloadFile(data, "application/pdf")));

你必须 subscribeObservable 才能执行任何操作。 Angular 示例返回 Observable 并附有 tap 运算符。你自己的例子是返回Subscription,这对调用你的方法的任何东西都没有用。

这是 Angular 服务的推荐设计模式;该服务创建Observable,这就像一个工作流和数据转换的合同,然后调用者可以subscribe 到它并获得工作的结果。

【讨论】:

  • 查看我对原始帖子的更新。我已经按照您和 Angular 文档的建议重新设计了解决方案。这仍然不能解决我最初的问题,即我无法使用 Angular 的 HttpClient 从 Web API 访问非 JSON 响应。
【解决方案2】:

我也有类似的需求,我的 Api 返回了一个 Pdf 文件对象。我首先尝试通过将“Accept”设置为“Accept”的标头对象传递:“application/pdf”。但这不起作用。

然后我简单地将httpOptions中的“responseType”设置为:

this._httpClient.post(apiUrl, filterParams, { responseType: 'blob' });

它成功了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 2019-12-12
    • 1970-01-01
    相关资源
    最近更新 更多