简介

  • 本教程将向你展示如何以一系列MJPEG帧的形式发送视频流。这里使用的技术是:
    • 以不可缓存的方式提供页面,并表明内容类型为multipart/x-mixed-replace。
    • 定期发送一个不同的JPEG文件的内容,取代以前的文件

单次文件上传大小为3MB

  • 修改宏MG_MAX_RECV_SIZE
    • mongoose.h中,宏MG_MAX_RECV_SIZE默认定义为3 * 1024 * 1024
    • 修改即可

文件上传问题

HTTP协议上传文件原理

HTTP 协议中的文件上传是通过 POST 请求来实现的,具体的原理如下:

  1. 客户端发送一个 HTTP POST 请求到服务器,并在请求头中指定 Content-Type 为 multipart/form-data。这告诉服务器该请求是一个包含多部分内容的表单数据。

  2. 服务器收到请求后,解析请求头中的 Content-Type,确认请求是一个文件上传请求。

  3. 客户端将要上传的文件分割成多个部分(或者称为数据包),每个数据包都包含一个文件的一部分内容。

  4. 客户端将每个数据包作为一个独立的部分,依次发送给服务器。每个数据包都会包含一些额外的元数据,例如文件名、文件类型等。

  5. 服务器接收到每个数据包后,根据数据包的元数据信息和内容进行处理。通常情况下,服务器会将接收到的数据包保存到临时文件或内存中。

  6. 当所有数据包都接收完毕后,服务器根据接收到的数据包重新构建原始文件,并将其保存到指定的位置。

需要注意的是,文件上传的过程中可能会涉及到数据包的分片、文件大小限制、上传进度监测等细节处理。一般来说,服务器端会提供相应的接口或库来处理文件上传,以简化开发过程。

Mongoose解决方案

  • 两种情况:
    • 要上传的文件很小–明显小于可用RAM的数量。例如,我们在一个有64MB内存的嵌入式Linux系统上运行Mongoose,并上传一些大小为1KB的JSON配置。在这种情况下,我们可以使用一个标准的HTML表单上传,并在一个POST请求中接收整个文件
    • 要上传的文件很大–与可用RAM的数量相比,或者明显超过这个数量。例如,我们想上传一个大小为512KB的新文件系统镜像到ESP8266设备上,该设备有大约30KB的可用RAM。在这种情况下,没有办法在内存中保存整个文件。它应该被分成小块处理,Mongoose应该接收每个小块并将其追加到写入的文件中,直到全部接收完毕。在这里,我们可以遵循两条路径:
      • 使用单个POST请求发送文件,将文件内容作为POST主体传递–即使用二进制上传。
      • 在客户端将文件分成小块(如2Kb),并将每个小块作为一个单独的POST请求发送。

form upload

binary upload, single POST

  • 当Mongoose收到一个大的HTTP请求时,它会缓冲传入的数据,对于每一个收到的数据块,它会产生MG_EV_HTTP_CHUNK请求。当一个完整的HTTP消息被缓冲时,那么最后一个零长度的MG_EV_HTTP_CHUNK被产生,然后是MG_EV_HTTP_MSG
  • 然而,服务器端可能不会等到完整的消息被缓冲在内存中,但它可以使用mg_http_delete_chunk()函数删除传入的chunk。如果块被删除,那么在最后一个零长度的块之后就不会产生MG_EV_HTTP_MSG。这样一来,服务器就可以在块到达时进行处理–例如,将块写入文件中。
  • MG_EV_HTTP_CHUNK消息也是为表单上传生成的。然而,Mongoose并不剥离多部分标记。如果表单上传的消息被保存到一个文件中,它将包含多部分标记。

  • 0长度的chunk是最后一个chunk。使用MG_IO_SIZE构建常数来限制服务器端的最大分块大小。

  • 服务器接收每个块,处理它并删除它。当收到最后一个分块时,发送一个响应。