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

如何使用netcat接收含多文件的HTTP响应并保存至磁盘?

嘿,这个需求我刚好折腾过,咱们一步步来搞定它!

核心思路

HTTP的multipart响应和tgz包不一样,它是用边界分隔符把每个文件拆分开的,每个文件还带着自己的HTTP头(比如包含文件名的Content-Disposition)。所以我们的步骤是:

  1. 从响应头部提取multipart的边界值
  2. 遍历响应内容,按边界拆分每个文件部分
  3. 从每个部分的头里提取文件名,然后把内容写入对应文件
方案1:用Awk处理文本文件场景

如果你要接收的都是文本类文件(比如txt、csv),用Awk脚本就能搞定,直接把命令链写成这样:

nc localhost 5000 | awk '
  BEGIN { boundary = ""; in_header = 1; in_body = 0; filename = ""; file_handle = "" }
  # 第一步:从Content-Type头里提取边界
  /^Content-Type: multipart/ {
    split($0, parts, /boundary=/)
    boundary = parts[2]
    gsub(/"/, "", boundary)  # 去掉边界值可能带的引号
  }
  # 遇到边界,关闭上一个文件(如果有的话),准备处理新文件
  $0 ~ "--" boundary {
    if (file_handle != "") {
      close(file_handle)
      file_handle = ""
    }
    in_header = 1
    in_body = 0
    filename = ""
    next
  }
  # 从Content-Disposition头里提取文件名
  in_header && /^Content-Disposition:/ {
    split($0, parts, /filename=/)
    filename = parts[2]
    gsub(/[";]/, "", filename)  # 去掉文件名里的引号和分号
    if (filename != "") {
      file_handle = filename
      printf "" > file_handle  # 创建空文件
      in_header = 0
      in_body = 1
    }
    next
  }
  # 空行是头部和正文的分隔符,跳过头部进入正文写入阶段
  in_header && /^$/ {
    in_header = 0
    if (filename != "") {
      in_body = 1
    }
    next
  }
  # 把正文内容写入文件,直到遇到下一个边界
  in_body && $0 !~ "--" boundary {
    print > file_handle
  }
  # 遇到结束边界(--boundary--),关闭文件并退出
  $0 ~ "--" boundary "--" {
    if (file_handle != "") {
      close(file_handle)
    }
    exit
  }
'
方案2:用Perl处理二进制文件场景

如果要接收图片、压缩包这类二进制文件,Awk可能会因为文本处理的特性搞乱二进制数据,这时候用Perl更靠谱,它能直接处理二进制流:

nc localhost 5000 | perl -e '
  my $boundary = "";
  my $in_header = 1;
  my $in_body = 0;
  my $filename = "";
  my $fh;

  while (<>) {
    # 提取边界并加上开头的--
    if (/^Content-Type: multipart\/.*boundary=(.*)$/) {
      $boundary = $1;
      $boundary =~ s/["]//g;
      $boundary = "--" . $boundary;
    }
    # 遇到边界,关闭上一个文件
    if (/^$boundary/) {
      if ($fh) {
        close $fh;
        undef $fh;
      }
      $in_header = 1;
      $in_body = 0;
      $filename = "";
      next;
    }
    # 提取文件名并打开文件(二进制模式)
    if ($in_header && /^Content-Disposition:.*filename=(.*)$/) {
      $filename = $1;
      $filename =~ s/[";]//g;
      if ($filename ne "") {
        open $fh, ">", $filename or die "Can't open $filename: $!";
        binmode $fh;  # 关键:启用二进制模式,避免换行符转换
        $in_header = 0;
        $in_body = 1;
      }
      next;
    }
    # 跳过头部结束的空行
    if ($in_header && /^$/) {
      $in_header = 0;
      next;
    }
    # 写入文件内容
    if ($in_body && !/^$boundary/) {
      print $fh $_;
    }
    # 处理结束标记,退出脚本
    if (/^$boundary--$/) {
      close $fh if $fh;
      exit;
    }
  }
'
补充:关于tgz的情况

你提到的tgz方案确实更简单——如果服务器返回的是一个tgz压缩包,直接用nc localhost 5000 | tar xzvf -就能自动解压所有文件到当前目录。但这个只适用于响应是单一tgz包的情况,而如果是HTTP multipart格式的多文件响应,就得用上面的multipart解析脚本了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:34:40