如何解析HTTP POST(文件上传)流?

3
我将使用ActionScript引擎上传文件,该引擎会选择文件并通过HTTP POST命令将文件发送到网络上。文档中说明POST消息如下:
POST /handler.cfm HTTP/1.1
  Accept: text/*
  Content-Type: multipart/form-data; 
  boundary=----------Ij5ae0ae0KM7GI3KM7ei4cH2ei4gL6 
  User-Agent: Shockwave Flash 
  Host: www.example.com 
  Content-Length: 421 
  Connection: Keep-Alive 
  Cache-Control: no-cache

  ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
  Content-Disposition: form-data; name="Filename"

  MyFile.jpg
  ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
  Content-Disposition: form-data; name="photo"; filename="MyFile.jpg"
  Content-Type: application/octet-stream

  FileDataHere
  ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
  Content-Disposition: form-data; name="Upload"

  Submit Query

  ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--

我在服务器端有一个C++程序,它监听80端口并解析POST消息。我只想要文件名和文件数据。如何使用C++解码文件数据?它是否是base64编码的?是否有库可以为我完成这项工作?我想解码二进制,并将其写入文件中,谢谢!


如果您在HTML中不给提交按钮命名,它将无法被POST到服务器(即“上传”部分):) - pmg
3个回答

5

不,没有编码。多部分消息的每个子部分的主体都以逐字节的形式包含在其中。因此,您必须小心选择一个在文件数据中不存在的边界字符串。

为了解析multipart/form-data表单提交,您需要足够的MIME解析器来解析头部,挑选出想要的参数,如boundaryname,并按边界字符串拆分接收到的消息。这并不完全是简单的,因此您可能需要考虑现有库

(不幸的是,浏览器在HTTP中实际执行的操作与RFC 1341中概述的标准MIME规则有些不同。特别是,字段名称和文件名参数往往包含非ASCII字符和未转义的引号。但如果您自己生成POST请求,希望您能避开这些争议的领域。)


1
在缺少“Content_Transfer_Encoding”头的情况下,假定数据以“7bit”编码(RFC 1521; RFC 1867; RFC 2616)。
我不知道是否有一个C库来解析/解码HTTP POSTs。但我相信一定有 :)

哦,伙计,我来这里不是为了看C++,而是特别想看一下用于解析边界数据的C库,我也相当确定有这样的库。 - Arthur Kushman

1
你可以上传任意大小的数据/文件。尝试这个解决方案。
const char* ctype = "multipart/form-data; boundary=----WebKitFormBoundaryfm9qwXVLSbFKKR88";
size_t content_length = 1459606;
http_payload* hp = new http_payload(ctype, content_length);
if (hp->is_multipart()) {
    int ret = hp->read_all("C:\\temp\\");
    if (ret < 0) {
        std::cout << hp->get_last_error() << std::endl;
        hp->clear();
    }
    else {
        std::string dir_str("C:\\upload_dir\\");
        ret = hp->read_files([&dir_str](http_posted_file* file) {
            std::string path(dir_str.c_str());
            path.append(file->get_file_name());
            file->save_as(path.c_str());
            file->clear(); path.clear();
            std::string().swap(path);
        });
        hp->clear();
        std::cout << "Total file uploaded :" << ret << std::endl;
    }
}
else {
    int ret = hp->read_all();
    if (ret < 0) {
        std::cout << hp->get_last_error() << std::endl;
        hp->clear();
    }
    else {
        std::cout << "Posted data :" << hp->get_body() << std::endl;
        hp->clear();

    }
}

https://github.com/safeonlineworld/web_jsx/blob/0d08773c95f4ae8a9799dbd29e0a4cd84413d108/src/web_jsx/core/http_payload.cpp#L402


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接