You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用httr提取API返回的application/xop+xml格式中的ZIP附件?

提取multipart/related响应中的ZIP附件

问题背景

向API发送POST请求后,返回multipart/related; type="application/xop+xml"格式的响应,其中包含一个名为tmp12345.zip的附件,但直接用writeBin保存整个响应内容无法打开ZIP文件。

核心解决方案

响应是多部分复合格式,必须根据响应头中的boundary值拆分内容,定位到对应附件的二进制块后单独保存,具体步骤如下:


1. 明确响应结构

响应头中的boundary是拆分多部分内容的关键标记(本例中为uuid:0ca94e9c-b817-4e87-9628-656cdd58be68),每一部分以--{boundary}开头,最终以--{boundary}--结尾。目标附件块包含Content-Disposition: attachment;name="tmp12345.zip"标识。

2. 具体实现(Python示例)

import requests

# 替换为你的API请求参数(已完成认证)
response = requests.post("https://your-api-endpoint", auth=("username", "password"), data=your_request_body)

# 从响应头提取boundary
content_type_header = response.headers["Content-Type"]
boundary = content_type_header.split('boundary="')[1].split('"')[0]
part_delimiter = f"--{boundary}".encode("utf-8")
end_delimiter = f"--{boundary}--".encode("utf-8")

# 拆分响应的二进制内容
response_parts = response.content.split(part_delimiter)

# 遍历查找目标附件
for part in response_parts:
    if b'Content-Disposition: attachment;name="tmp12345.zip"' in part:
        # 分离块头部和二进制内容(空行分隔)
        header_split_pos = part.find(b"\r\n\r\n")
        if header_split_pos != -1:
            zip_binary = part[header_split_pos + 4:]
            # 移除结尾的结束分隔符
            if zip_binary.endswith(end_delimiter):
                zip_binary = zip_binary[:-len(end_delimiter)]
            # 保存ZIP文件
            with open("extracted.zip", "wb") as zip_file:
                zip_file.write(zip_binary)
            break

3. R语言实现示例

library(httr)

# 发送认证后的POST请求
api_response <- POST(
  url = "https://your-api-endpoint",
  authenticate("your-username", "your-password"),
  body = your_request_body
)

# 提取boundary
content_type <- headers(api_response)$`Content-Type`
boundary <- sub('.*boundary="([^"]+)".*', "\\1", content_type)
delimiter <- paste0("--", boundary)
raw_content <- content(api_response, "raw")

# 拆分内容并定位附件
content_str <- rawToChar(raw_content)
parts <- strsplit(content_str, delimiter)[[1]]

for (part in parts) {
  if (grepl('Content-Disposition: attachment;name="tmp12345.zip"', part)) {
    # 找到头部结束的空行位置
    header_end <- regexpr("\r\n\r\n", part)[1]
    if (header_end != -1) {
      # 计算二进制内容在原始raw数据中的起始位置
      raw_start <- header_end + 4
      # 提取并保存二进制数据
      zip_raw <- raw_content[raw_start:(length(raw_content) - nchar(delimiter) - 2)]
      writeBin(zip_raw, "extracted.zip")
      break
    }
  }
}

关键注意事项

  • 必须使用原始二进制内容处理,避免将响应转换为文本后再转回二进制,防止编码破坏ZIP结构。
  • 拆分时要严格匹配boundary的格式,注意前后的--标记。

内容的提问来源于stack exchange,提问作者fsumathguy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:35:57