我使用以下类型的函数来读取远程文件
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使用chkksizes读取文件,如2kb,3kb,7kb等,而不是指定的chunksize
我搜索了几个小时但却无法找出问题。我实际上是在尝试下载远程文件并上传它,文件很大,这会在服务器上造成内存问题,因此我无法使用file_get_contents。
由于在开始上传之前需要预先定义chunksize,因此改变chunksize会导致上传混乱。
---- ----编辑
如果流被读缓冲并且它不代表普通文件, 最多一次读取最多等于块大小的字节数 (通常是8192);取决于先前缓冲的数据, 返回数据的大小可能大于块大小。
无论如何要绕过这个?
或除了使用fopen和fread之外,如何从块中读取远程文件中的数据?
答案 0 :(得分:0)
我发现默认情况下PHP引擎的块大小为8kB http://php.net/manual/en/function.fread.php
示例代码如果流被读缓冲并且它不代表普通文件, 最多一次读取最多等于块大小的字节数 (通常是8192);取决于先前缓冲的数据, 返回数据的大小可能大于块大小。
BUFSIZ
中的只能小于内部默认的块大小。
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但后续的Chunks只填充了不到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);
答案 1 :(得分:-1)
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.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我搜索了几个小时
......在所有错误的地方似乎
编辑:作为旁注 - 问题在哪里?