c++ - Boost Asio 和 Beast multipart/form-data 从 Streambuf 保存二进制文件

标签 c++ boost-asio boost-beast

我的结果看起来像...

POST /post HTTP/1.1
Host: localhost:3003
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0)    
Gecko/20100101 Firefox/62.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:3003/profile
Content-type: multipart/form-data
Content-Length: 14708
Cookie: mycookie=7bdbed41954cd4133a172acb92988e58
Connection: keep-alive

-----------------------------4636945214860352321751082034
...
binary characters...
...
-----------------------------4636945214860352321751082034

获取自

boost::asio::async_read(
    socket_,
    strmbuffer_,
    boost::asio::transfer_exactly(bytes_to_transfer),
    strand_.wrap(
    [this, self](boost::system::error_code ec, std::size_t bytes_transferred)
    {
        std::stringstream ss;
        ss << buffer_data;  // from socket_.async_read_some()
        ss << &strmbuffer_; // now stringstream contains everything

        // the character routine which writes the above
        // and which i use for output...

        std::string output_file = "../../upload/test.png";
        std::ofstream outfile(output_file);
        char c;
        unsigned bl = boundary.length();
        bool endfile = false;
        unsigned bufsize = 512;
        if(outfile){
            char buffer[bufsize];
            while(!endfile){
                // here looks like below
                // to find and pass the first boundary
            }   // then stream continues...
            while(!endfile){
                unsigned j = 0;
                unsigned k;
                memset(buffer, 0, bufsize); // redundant
                while(j < bufsize && ss.get(c) && !endfile){
                    buffer[j] = c;
                    k = 0;
                    while(boundary[bl - 1 - k] == buffer[j - k]){
                        if(k >= bl - 1){
                            endfile = true;
                            break;
                        }
                        k++;
                     }
                     j++;
                 }
                 outfile.write(buffer, j);
                 j = 0;
             }
         }
    }
);

...本质上。因此,接收

socket_.async_read_some()

给我一​​个

boost::array<char, 8192> buffer_;

这给了我http请求信息。但在 multipart/form-data 的情况下,它读取通过了第一个边界,这意味着下一个 read() 看不到它。啊! (async_read_until() 也是如此。)所以,在

boost::asio::async_read()

我转换

boost::asio::streambuf strmbuffer_;

到字符串流并将它们加在一起以获得上面的 std::cout 结果。

我根本不相信我应该使用 stringstream。但是上面的例程(使用 stringstream)在 Boost::Beast 中工作得很好。在 Asio 中则不然。不幸的是,在 Beast 中接收 http 请求的 string_body 类型有一个严格的大小限制,我相信是 1 兆。不知道如何改变它。

我在任何地方都找不到关于这个主题的太多信息。也许,这些信息太危险了。如果他们告诉我,他们就必须杀了我。我应该在 Asio 中使用什么来将二进制数据写入磁盘?

最佳答案

默认情况下,HTTP 请求解析器以 1 MB 限制开始。这是为了防止客户端发送大量或无限量的正文数据时出现资源耗尽攻击。您可以通过使用所需的最大值调用 parser::body_limit 轻松更改此限制。文档中对此进行了描述:

https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/ref/boost__beast__http__parser/body_limit.html https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/using_http/buffer_oriented_parsing.html

为了调整解析器参数,例如主体限制(或 header 限制),您将需要使用“解析器流操作”接口(interface)。对此进行了解释:

https://www.boost.org/doc/libs/1_68_0/libs/beast/doc/html/beast/using_http/parser_stream_operations.html

关于c++ - Boost Asio 和 Beast multipart/form-data 从 Streambuf 保存二进制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53456123/

相关文章:

c++ - 氧优化

c++ - 如何计算整数中的零位数?

C++ boost/asio 客户端不连接到服务器

c++ - boost::beast 同步 http 客户端超时

c++ - beast async_read() 是如何工作的?它有一个选项吗?

c++ - 使用 std::map [] 运算符交换与分配(const 问题)

c++ - SetWinEventHook 和 GetMessage c++

c++ - Boost.Asio 设计的示例莫名其妙地阻塞

c++ - 在 boost::asio 中清除来自串口的输入数据

c++11 - Boost Beast HTTP