如何在Linux中从HTTP MIME编码的消息中提取文件数据?

如何在Linux中从HTTP MIME编码的消息中提取文件数据?,linux,bash,sed,awk,Linux,Bash,Sed,Awk,我有一个程序,接受HTTP post文件并将所有post结果写入一个文件,我想写一个脚本来删除HTTP头,只留下二进制文件数据,怎么办 文件内容如下(我需要内容类型:application/octet stream和------KM7cH2GI3cH2Ef1Ij5gL6GI3Ij5GI3之间的数据: POST /?user_name=vvvvvvvv&size=837&file_name=logo.gif& HTTP/1.1^M Accept: text/*^M Cont

我有一个程序,接受HTTP post文件并将所有post结果写入一个文件,我想写一个脚本来删除HTTP头,只留下二进制文件数据,怎么办

文件内容如下(我需要
内容类型:application/octet stream
------KM7cH2GI3cH2Ef1Ij5gL6GI3Ij5GI3
之间的数据:

POST /?user_name=vvvvvvvv&size=837&file_name=logo.gif& HTTP/1.1^M
Accept: text/*^M
Content-Type: multipart/form-data; boundary=----------KM7cH2GI3cH2Ef1Ij5gL6GI3Ij5GI3^M
User-Agent: Shockwave Flash^M
Host: 192.168.0.198:9998^M
Content-Length: 1251^M
Connection: Keep-Alive^M
Cache-Control: no-cache^M
Cookie: cb_fullname=ddddddd; cb_user_name=cdc^M
^M
------------KM7cH2GI3cH2Ef1Ij5gL6GI3Ij5GI3^M
Content-Disposition: form-data; name="Filename"^M
^M
logo.gif^M
------------KM7cH2GI3cH2Ef1Ij5gL6GI3Ij5GI3^M
Content-Disposition: form-data; name="Filedata"; filename="logo.gif"^M
Content-Type: application/octet-stream^M
^M
GIF89an^@I^^M
------------KM7cH2GI3cH2Ef1Ij5gL6GI3Ij5GI3^M
Content-Disposition: form-data; name="Upload"^M
^M
Submit Query^M
------------KM7cH2GI3cH2Ef1Ij5gL6GI3Ij5GI3-

如果您使用Python,将允许您解析一个多部分MIME文档。

这可能是一个疯狂的想法,但我会尝试使用procmail剥离标题。

这可能包含一些打字错误或其他内容,但无论如何请容忍。首先确定边界(
输入
是包含数据管道的文件,如果需要):

然后过滤
Filedata
部分:

fd='Content-Disposition: form-data; name="Filedata"'
sed -n "/$fd/,/$boundary/p"
最后一部分是过滤一些额外的行-前面的标题行,包括空行和边界本身,因此将最后一行从previous更改为:

sed -n "/$fd/,/$boundary/p" | sed '1,/^$/d' | sed '$d'
  • sed-n/$fd/,/$boundary/p”
    过滤
    Filedata
    头和边界(包括)之间的行
  • sed'1,/^$/d'
    正在删除第一行之前的所有内容(因此会删除标题),并且
  • sed'$d'
    删除最后一行(边界)
在此之后,您等待Dennis(参见注释)对其进行优化,您将得到以下结果:

sed "1,/$fd/d;/^$/d;/$boundary/,$d"
既然您已经来到这里,请从头开始,按照Ignacio的建议去做。原因-这可能无法(可靠地)实现,因为GIF是二进制数据

啊,这是一个很好的练习!无论如何,对于
sed
的爱好者来说,这是一个非常好的页面:


出色的信息。

看看for Perl。它有一组丰富的类;我相信您可以在几行中组合一些内容。

您希望在文件处理时这样做,还是在文件处理后这样做

几乎任何脚本语言都应该可以工作。我的AWK有点生疏,但是

awk '/^Content-Type: application\/octet-stream/,/^--------/'
这将打印
应用程序/octet流
-----------
行之间的所有内容。它还可能同时包括这两行,这意味着您必须执行更复杂的操作:

BEGIN {state = 0}
{
    if ($0 ~ /^------------/) {
        state = 0;
    }
    if (state == 1) {
        print $0
    }
    if ($0 ~ /^Content-Type: application\/octet-stream/) {
        state = 1;
    }
}
application\/octet-stream
行位于print语句之后,因为您希望在看到
application/octet-stream
后将
state
设置为
1


当然,作为Unix,您可以通过awk将程序的输出导入,然后保存文件。

无需在结尾处调用
sed
三次:
sed“1,/$fd/d;/$boundary/,$d”
@Dennis Sweet-只需要另一个(在Filedata头之后删除额外的头):
sed“1,/$fd/d;//$/d;/$boundary/,$d”
。我将编辑以添加。
BEGIN {state = 0}
{
    if ($0 ~ /^------------/) {
        state = 0;
    }
    if (state == 1) {
        print $0
    }
    if ($0 ~ /^Content-Type: application\/octet-stream/) {
        state = 1;
    }
}