简体   繁体   English

如何在没有Content-Length标头的情况下流式传输HTTP文件?

[英]How to stream an HTTP file upload without the Content-Length header?

Is it possible to upload a file to an apache php server without including the content-length header ? 是否可以将文件上传到apache php服务器而不包含内容长度标题?

I am trying to stream a file that I am creating on the fly as a file upload. 我正在尝试将我正在创建的文件作为文件上传流式传输。 When I don't use the content-length header I got the apache "501 Method Not Implemented". 当我不使用内容长度标题时,我得到了apache“501 Method Not Implemented”。

$sock = fsockopen($host,80,$errno, $error);
fwrite($sock, "POST $resource HTTP/1.1\r\n" .
                     "Host: $host\r\n\r\n");
fwrite($sock,fread($readHandle,filesize($file)));

If I include the content-length it works fine. 如果我包含内容长度,它工作正常。

The server is reading from php://input 服务器正在从php://输入读取

According to the HTTP spec you aren't technically required to specify the Content-Length header. 根据HTTP规范,技术上不需要指定Content-Length标头。 From RFC 2616 14.13 : 来自RFC 2616 14.13

Applications SHOULD use this field to indicate the transfer-length of the message-body, unless this is prohibited by the rules in section 4.4. 应用程序应该使用此字段来指示消息正文的传输长度,除非4.4节中的规则禁止这样做。

However, this is a pretty standard requirement for most servers, and they'll generally send back an error response if the Content-Length header is missing or incorrectly specified. 但是,对于大多数服务器来说,这是一个非常标准的要求,如果Content-Length标头丢失或指定不正确,它们通常会发回错误响应。 For all intents and purposes, SHOULD in this case equates to MUST . 出于所有意图和目的,在这种情况下应该等同于必须

The problem is that (especially with keep-alive connections), the server doesn't know when your request message actually ends without the Content-Length header. 问题是(特别是对于保持活动连接),服务器不知道您的请求消息何时实际结束而没有Content-Length标头。 The other option if you're streaming a request entity body is to send a Transfer-Encoding: chunked header and manually send one chunk of the entity body at a time. 如果您正在流式传输请求实体主体,则另一个选项是发送Transfer-Encoding: chunked标头并一次手动发送一个实体主体块。

So in summary, if you want to send an entity body with your message but don't want to send a Content-Length header, your only real option is to send a chunked HTTP message . 总而言之,如果您希望发送带有消息的实体主体但又不想发送Content-Length标头,那么您唯一真正的选择是发送分块的HTTP消息 This is basically required if you want to stream that entity body and don't know its length ahead of time. 如果您想要流式传输该实体主体并且不知道其长度,则基本上这是必需的。

How to chunk-encode an HTTP entity body for streaming ... 如何对HTTP实体主体进行块编码以进行流式处理...

Transfer-Encoding: chunked means that you're encoding the entity body of the HTTP message according to the constraints laid out in RFC2616 Sec3.6.1 . Transfer-Encoding: chunked意味着您根据RFC2616 Sec3.6.1中规定的约束对HTTP消息的实体主体进行编码。 This encoding format can be applied to either requests or responses (duh, they're both HTTP messages). 这种编码格式可以应用于请求或响应(duh,它们都是HTTP消息)。 This format is extremely useful because it allows you to start sending an HTTP message right away before you know the size of the entity body or even exactly what that entity body is going to be. 这种格式非常有用,因为它允许您在知道实体主体的大小之前立即开始发送HTTP消息,甚至可以确切地知道该实体主体的内容。 In fact, this is exactly what PHP does transparently for you when you echo any output without having sent a length header like header('Content-Length: 42') . 实际上,这正是PHP在没有发送像header('Content-Length: 42')这样的长度header('Content-Length: 42')情况echo任何输出时透明地为你做的事情。

I'm not going to get into details of chunked encoding -- that's what the HTTP spec is for -- but if you want to stream a request entity body you need to do something like this: 我不打算详细介绍分块编码 - 这就是HTTP规范的用途 - 但是如果你想要流一个请求实体,你需要做这样的事情:

<?php

$sock = fsockopen($host,80,$errno, $error);
$readStream = fopen('/some/file/path.txt', 'r+');

fwrite($sock, "POST /somePath HTTP/1.1\r\n" .
              "Host: www.somehost.com\r\n" .
              "Transfer-Encoding: chunked\r\n\r\n");

while (!feof($readStream)) {
    $chunkData = fread($readStream, $chunkSize);
    $chunkLength = strlen($chunkData);
    $chunkData = dechex($chunkLength) . "\r\n$chunkData\r\n";

    fwrite($sock, $chunkData);
}

fwrite($sock, "0\r\n\r\n");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM