TinyWebServer icon indicating copy to clipboard operation
TinyWebServer copied to clipboard

开发上传文件功能时出现稍大文件上传失败现象

Open ZYunfeii opened this issue 2 years ago • 6 comments

HTTP部分利用input type = file上传

<div align="center">
        <form action="d" method="post" enctype="multipart/form-data">
            <div>
                <!-- 上传文件 -->
                <p>
                    <input type="file" name="filename">
                </p>
    
            </div>
            <input type="submit" value="提交">
        </form>

</div>

当服务器recv报文时总会出现接受不完bytes_read = -1的情况,当在recv前增加一段时间sleep后能够接受稍大一点(不到1MB)文件,但更大时依旧失败。怀疑可能是bytes_read = -1时文件并未传输完成就开始解析报文了。

        // m_sleep(200); // 增加了这一句可以稍微接受大一点的文件
        int count = 0; 
        while (true)
        {
            bytes_read = recv(m_sockfd, m_read_buf + m_read_idx, READ_BUFFER_SIZE - m_read_idx, 0);
            std::cout<<bytes_read<<std::endl;
            if (bytes_read == -1)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK){ 
                    break;
                }
                std::cout<<"errno:"<<errno<<std::endl;
                return false;
            }
            else if (bytes_read == 0)
            {
                return false;
            }
            m_read_idx += bytes_read;
        }
        return true;

ZYunfeii avatar Apr 10 '22 03:04 ZYunfeii

我也是这个问题 老哥你解决了吗

caichangzhao avatar Apr 26 '22 07:04 caichangzhao

我也是这个问题 老哥你解决了吗

解决了 不过换了个server项目 我个人感觉这个框架是存在小问题的

ZYunfeii avatar Apr 26 '22 13:04 ZYunfeii

我也是这个问题 老哥你解决了吗

解决了 不过换了个server项目 我个人感觉这个框架是存在小问题的

请问一下换了哪个server项目呀?

kruicy avatar May 12 '22 05:05 kruicy

问题好像出现在这:文件过大时,第一次解析请求体得到的结果是不完整,行状态变成LINE_OPEN,此时循环并没有结束,会执行 line_state = parse_line()。在 parse_line() 中check_idx会发生变化,导致 parse_content()函数中的判断条件永远不会成立,一直返回NO_REQUEST的状态。

// process_read()函数
while (((check_state == CHECK_STATE_CONTENT) && (line_state == LINE_OK)) || ((line_state = parse_line()) == LINE_OK))
{ 
  case CHECK_STATE_CONTENT:
        ret = parse_content(text);  
        if (ret == GET_REQUEST) {
            return do_request();
        }
        line_state = LINE_OPEN;
        break;
}

我的解决是这样的,在parse_line()函数开头加入以下判断:

if (check_state == CHECK_STATE_CONTENT) {
    if (read_idx >= content_len + check_idx) {
        return LINE_OK;
    }
    else {
        return LINE_OPEN;
    }
}

经过测试,可以实现MB级别的文件上传。 如果有理解不对的地方还请指出。

wlufy avatar Mar 02 '23 07:03 wlufy

我想问一下上面的老哥每个http_conn对象接收缓冲区的大小只有2048,把接收缓冲区2048大小填满了,怎么实现稍大一点的文件上传

userwang12 avatar Nov 14 '23 15:11 userwang12

@userwang12 不知道现在逻辑变没变,一年多了。但当时的逻辑没有解决粘包导致大文件会上传失败,这是关键点,至于你说的缓存有关系但不是直接关系。

ZYunfeii avatar Apr 10 '24 14:04 ZYunfeii