【问题标题】:Return JSON and a File返回 JSON 和一个文件
【发布时间】:2015-08-13 09:55:48
【问题描述】:

如何返回 JSON 响应和文件响应:

现在我这样做:

runNumber = "A0001"
response = None
try:
    response = make_response("Line One\r\nLine Two\r\n")
    response.headers["Content-Disposition"] = "attachment; filename=" + runNumber + ".txt"
except MyCustomException as e:
    response = jsonify(error=e.value, runnumber=runNumber)
except:
    raise
return(response)

但这仅允许我返回 JSON 或文件。在某些情况下,我想同时退货。

[编辑:] 我想返回 JSON 和文件的情况是当有一个关于文件内容的警告时,用户应该在使用文件之前检查。

如果这不可能,我会将警告添加到文件的内容中。

【问题讨论】:

  • 客户端如何将文件和 JSON 部分再次分离出来?
  • 这在 HTTP 中根本不可能 - 您的响应有一个 Content-Type(和一个 Content-Disposition 就这一点而言)。浏览器根本不以任何标准化方式支持多部分响应(12

标签: python flask


【解决方案1】:

您不能只返回两个响应。你只能退回那个。

这意味着如果你真的需要返回 JSON 和文件,你需要想出一个方案,让你在 一个 响应中返回这两者并让客户端再次分离出文件和 JSON 部分。

对此没有标准。无论您想出什么,都需要仔细记录,以便您的客户明确处理。

您可以使用自定义标头来存储 JSON 数据,例如:

response = make_response("Line One\r\nLine Two\r\n")
response.headers["Content-Disposition"] = "attachment; filename=" + runNumber + ".txt"
response.headers['X-Extra-Info-JSON'] = json.dumps(some_object)

或者您可以将文件内容放入 JSON 数据中。 JSON 不是二进制数据的最佳格式,您可能需要先将二进制数据编码为 Base64:

filedata = "Line One\r\nLine Two\r\n".encode('base64')
return jsonify(name=runNumber + '.txt', data=filedata)

或者您可以创建一个多部分 MIME 文档,其方式与 POST multipart/form-data 正文的工作方式相同。

您选择的内容取决于您的用例(使用您的 API 的客户端类型)和数据大小(JSON 响应中的兆字节文件数据不太可行)。

【讨论】:

    【解决方案2】:

    我在发送音频文件及其副本时遇到了类似的问题。不幸的是,我们不能为一个 API 请求发送两个响应。此外,对单个任务进行两次 API 调用也没有任何意义。我的解决方法是通过 JSON 传递编码为字符串的文件的二进制数据,并在前端对其进行解码。我在后端使用了 python 和 flask,在前端使用了 react-js。这是代码的sn-p。您必须根据您发送的文件修改解码部分。

    Python:

    import base64
    response = {
        "audioContent": base64.b64encode(binaryData).decode(),
        "botText": botText
    }
    return json.dumps(response)
    

    JS:

    fetch(URL, requestData).then((response) => response.json()).then((data) => {
        var binary_string = window.atob(data.audioContent);
        var len = binary_string.length;
        var bytes = new Uint8Array(len);
        for (var i = 0; i < len; i++) {
          bytes[i] = binary_string.charCodeAt(i);
        }
        // console.log("Binary Data: ", binaryData);
        var url = window.URL.createObjectURL(
          new Blob([bytes.buffer], { type: "audio/mp3" })
        );
        console.log("URL: ", url);
        var a = new Audio(url);
        a.play();
    }
    

    有两点要记住:

    1. 当要发送的文件较小时,此方法效果最佳。大文件通常会影响您的 API 响应
    2. 在我的情况下,前端文件的解码速度很慢。我没有太多时间来提高性能,但它为我完成了任务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-16
      • 2018-10-08
      • 2021-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-13
      相关资源
      最近更新 更多