【问题标题】:Get PDF from WebAPI and download from UI, but data gets corrupted从 WebAPI 获取 PDF 并从 UI 下载,但数据已损坏
【发布时间】:2019-08-16 23:19:53
【问题描述】:

我从 UI 调用 Web API 控制器,然后从 SSRS 获取报告。它在响应的内容中插入字节并将其发送到 UI,在那里它以 PDF 格式下载。

在我的 Web API 控制器中,我将报告字节写入测试 PDF 文件,以检查 pdf 的内容并查看数据是否正确,即正确。但是,当从我的 UI 下载 PDF 并打开它时,我得到一个空白页文档。当我检查 Fiddler 中的响应内容时,我可以看到数据已损坏并且与测试 PDF 文件数据不匹配。

服务器端:

[HttpPost]
public HttpResponseMessage GetInstancePdf(InstancePdfModel model) {
  var bytes = _digitalFormService.GetInstancePdf(model.ClientGuid, model.InstanceGuid, model.InstanceVersion);

  File.WriteAllBytes(@ "c:\temp\test.pdf", bytes);

  var response = Request.CreateResponse();

  response.Content = new ByteArrayContent(bytes);
  response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(DispositionTypeNames.Inline) {
    FileName = "file.pdf"
  };
  response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

  return response;
}

客户端:

$scope.downloadPdf = function(instance) {
  $scope.isBusy = true;
  digitalFormService.getInstancePdf(instance.instanceGuid, instance.instanceVersion).then(function(data) {
    if (data.status === 200) {
      const file = new Blob([data.data], {
        type: data.headers("Content-Type")
      });
      if (navigator.appVersion.toString().indexOf(".NET") > 0) {
        window.navigator.msSaveBlob(file, (`${instance.name} ${(new Date()).toLocaleString()}`).replace(",", ""));
      } else {
        //trick to download, store a file having its URL
        const fileUrl = URL.createObjectURL(file);
        const a = document.createElement("a");
        a.href = fileUrl;
        a.target = "_blank";
        a.download = (`${instance.name} ${(new Date()).toLocaleString()}`).replace(",", "");
        document.body.appendChild(a);
        a.click();
      }
    } else {
      debugger;
    }
    $scope.isBusy = false;
  });
};

function getInstancePdf(instanceGuid, instanceVersion) {
  var data = {
    clientGuid: digitalFormConfig.clientToken,
    instanceGuid: instanceGuid,
    instanceVersion: instanceVersion
  };
  return $http({
    url: digitalFormConfig.serverUrl +
      "api/DigitalForm/GetInstancePdf",
    dataType: "json",
    data: data,
    method: "POST"
  }).then(function(response) {
      return response;
    },
    function() {
      return $q.reject("No Data");
    });
}

我希望我下载的 PDF 是一个信息文档,与保存在 Web API 控制器中的测试 PDF 文件相匹配,但我得到的是一个空白文档(与测试文件的页数相同,但为空白)。

我使用 Fiddler 检查响应正文。当我将 Fiddler 中的响应正文保存为 pdf 时 - 一切都很好。所以我确信我的服务器端代码是正确的。问题一定出在客户端的某个地方。

有什么帮助吗?谢谢。

【问题讨论】:

  • 不是这方面的权威,但看起来您正在接收二进制数据和 JS 期望字符串作为响应。我想从服务器获取链接并在选项卡中打开它会是一个更好的选择
  • 我使用 Fiddler 检查响应正文。当我将 Fiddler 中的响应正文保存为 pdf 时 - 一切都很好。所以我确信我的服务器端代码是正确的。问题一定出在客户端的某个地方。
  • 如果您不发布数据,这项工作会更容易。我真的想不出任何理由 ClientGuid InstanceGuidInstanceVersion 不应该用作查询字符串参数,而不是放在对象中并发布。将文件作为获取请求提供比将其作为对 JQuery json 帖子的响应要容易得多。

标签: javascript c# angularjs asp.net-web-api


【解决方案1】:

我发现了错误。该错误位于客户端服务中。代码应如下所示:

function getInstancePdf(instanceGuid, instanceVersion) {
    var data = {
        clientGuid: digitalFormConfig.clientToken,
        instanceGuid: instanceGuid,
        instanceVersion: instanceVersion
    };
    return $http({
        responseType: "arraybuffer",
        url: digitalFormConfig.serverUrl +
            "api/DigitalForm/GetInstancePdf",
        dataType: "json",
        data: data,
        method: "POST"
    }).then(function (response) {
            return response;
        },
        function () {
            return $q.reject("No Data");
        });
}

responseType: "arraybuffer", 行之前被省略了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多