我正在使用以下类型的函数来读取远程文件
define('BUFSIZ', 4095);
$url = "file url";
$rfile = fopen($url, 'r');
$lfile = fopen(basename($url), 'w');
while(!feof($rfile))
fwrite($lfile, fread($rfile, BUFSIZ), BUFSIZ);
fclose($rfile);
fclose($lfile);
但fread读取的文件具有2kb、3kb、7kb等块大小,而不是指定的块大小
我找了好几个小时都没找到问题。
实际上,我正在尝试下载一个远程文件并上传,文件很大,这会在服务器上产生内存问题,因此我无法使用file_get_contents。
由于在开始上传之前需要预先定义chunksize,因此改变chunksize会使上传变得混乱。
----编辑----
如果流是读缓冲的并且它不表示普通文件,最多一次读取最多等于块大小的字节数(通常为8192);根据先前缓冲的数据返回的数据的大小可以大于块大小。
有办法绕过这个吗?
或者除了使用fopen和fread之外,我如何从远程文件中读取数据块
我发现PHP引擎的Chunk大小默认为8kB
http://php.net/manual/en/function.fread.php
如果流是读缓冲的并且它不表示普通文件,最多一次读取最多等于块大小的字节数(通常为8192);根据先前缓冲的数据返回的数据的大小可以大于块大小。
在示例代码中CCD_ 1只能小于内部默认块大小。
fread($rfile, BUFSIZ);
但是,如果从远程源读取,实际读取的数据量仍然取决于网络带宽。
当您在Linux上使用strace
监控脚本时,您可以看到这一点:
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("<remote.ip>")}, 16) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=3, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 3000) = 1 ([{fd=3, revents=POLLOUT}])
getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
fcntl(3, F_SETFL, O_RDWR) = 0
sendto(3, "GET /remote_file.txt HTTP"..., 181, MSG_DONTWAIT, NULL, 0) = 181
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 3000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "HTTP/1.1 200 OK'r'nDate: Mon, 15 M"..., 8192, MSG_DONTWAIT, NULL, NULL) = 4320
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 3000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "'362F'334'350h't'350 '211R'200'272'312}'320Ftn~'240'350'32k'177'265'333'''257'222'345?'203"..., 8192, MSG_DONTWAIT, NULL, NULL) = 8192
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "'350", 1, MSG_PEEK, NULL, NULL) = 1
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 3000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "'350'260r'205D'5'343'377'323'357'306B6'335|'213OM'205'237i'236'306'356('304-'214F'305=>"..., 8192, MSG_DONTWAIT, NULL, NULL) = 1834
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 3000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "/'26'v'f'250!('2'22'342'250'235i'fKQe'2058'322'275'315:'270f'266'24R'326bn'371"..., 8192, MSG_DONTWAIT, NULL, NULL) = 1440
poll([{fd=3, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, 0) = 0 (Timeout)
我们看到,第一个下载的Chunk只有4kB,只有第二个真正装满了8kB,但随后的Chunk只装满了小于2kb的
在这种情况下,带宽确实限制了下载
上传也会发生同样的情况
您可以使用PHP函数stream_set_chunk_size()
更改连接的块大小
http://php.net/manual/en/function.stream-set-chunk-size.php
$rfile = fopen($url, 'r');
$lfile = fopen(basename($url), 'w');
stream_set_chunk_size($rfile, BUFSIZ);
stream_set_chunk_size($lfile, BUFSIZ);
http://php.net/manual/en/function.fread.php声明
if the stream is read buffered and it does not represent a plain file,
at most one read of up to a number of bytes equal to the chunk size
(usually 8192) is made; depending on the previously buffered data, the
size of the returned data may be larger than the chunk size.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我搜索了几个小时
在所有错误的地方,似乎
编者按:顺便提一下,问题在哪里?