IIS 中的文件下载随机失败 PHP
File downloads are randomly failing in IIS with PHP
我们有一个网站可以将文件流式传输给我们的客户。现在,我们开始拥有大于 300Mb 的文件,并且下载随机失败,原因不明。我们收到 "the download was interrupted" 错误。
我们登录到服务器并发现 PHP 进程有时会在下载开始时关闭,但事件查看器或日志中没有任何重要信息。
这是提供下载的代码:
public function downloadAction($asset, $csrfToken) {
if ($this->securityContext->isCsrfProtectionTokenValid($csrfToken) === FALSE) {
throw new \TYPO3\Flow\Security\Exception\AccessDeniedException();
}
// This is a : \TYPO3\Flow\Resource\Resource
$resource = $asset->getResource();
$stream = $resource->getStream();
if (FALSE === $stream) {
$this->throwStatus(500);
}
try {
$streamMetadata = stream_get_meta_data($stream);
$modified = filemtime($streamMetadata['uri']);
$filename = $asset->getResource()->getFilename();
$this->response->setStatus(200);
$this->response->setHeader('Content-Type', 'application/octet-stream');
$this->response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
$this->response->setHeader('Last-Modified', gmdate('r', $modified));
$this->response->setHeader('Content-Length', $asset->getResource()->getFileSize());
$this->response->setHeader('Content-transfer-encoding', 'binary');
$this->response->sendHeaders();
@set_time_limit(86400);
$fileBuffer = 8192;
while (!feof($stream)) {
print(fread($stream, $fileBuffer));
ob_flush();
flush();
}
} finally {
fclose($stream);
}
return '';
}
这是我们的设置:
- Windows 服务器 2008 R2
- IIS 7.5
- PHP 5.5.30
我试过的:
我尝试将 memory_limit 增加到 1024Mb,增加超时,增加脚本执行时间,但我们没有从增加这些中获得任何好处。
从事件查看器中,我们在下载失败时收到很多错误消息:
Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: unknown, version: 0.0.0.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x0000000000d94b98
Faulting process id: 0x26a0
Faulting application start time: 0x01d1c3157fec8818
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: unknown
Report Id: 9ea4b22a-2f09-11e6-8366-00155d016700
Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: nativerd.dll, version: 7.5.7601.17855, time stamp: 0x4fc85321
Exception code: 0xc0000005
Fault offset: 0x000000000000f4d3
Faulting process id: 0x2170
Faulting application start time: 0x01d1c310490342e2
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: c:\windows\system32\inetsrv\nativerd.dll
Report Id: 9ea48b1a-2f09-11e6-8366-00155d016700
Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: iisfcgi.dll, version: 7.5.7601.17514, time stamp: 0x4ce7c6cb
Exception code: 0xc0000005
Fault offset: 0x0000000000007a47
Faulting process id: 0x28b8
Faulting application start time: 0x01d1c3016d933dec
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: C:\Windows\System32\inetsrv\iisfcgi.dll
Report Id: 82a04d74-2f03-11e6-8366-00155d016700
编辑 1
看起来修改缓冲区并将其设置为 12000 有效,但不能设置为 11999。这是什么魔法?
您是否尝试过将 fread() 替换为 readfile()?它不是打开文件处理程序,而是通过 php 读取和传输文件块,而是直接将文件内容流式传输到网络服务器。
显然,将 $fileBuffer
放在 12000
可以,但不能放在 11999
... 但是为什么呢?
我们有一个网站可以将文件流式传输给我们的客户。现在,我们开始拥有大于 300Mb 的文件,并且下载随机失败,原因不明。我们收到 "the download was interrupted" 错误。
我们登录到服务器并发现 PHP 进程有时会在下载开始时关闭,但事件查看器或日志中没有任何重要信息。
这是提供下载的代码:
public function downloadAction($asset, $csrfToken) {
if ($this->securityContext->isCsrfProtectionTokenValid($csrfToken) === FALSE) {
throw new \TYPO3\Flow\Security\Exception\AccessDeniedException();
}
// This is a : \TYPO3\Flow\Resource\Resource
$resource = $asset->getResource();
$stream = $resource->getStream();
if (FALSE === $stream) {
$this->throwStatus(500);
}
try {
$streamMetadata = stream_get_meta_data($stream);
$modified = filemtime($streamMetadata['uri']);
$filename = $asset->getResource()->getFilename();
$this->response->setStatus(200);
$this->response->setHeader('Content-Type', 'application/octet-stream');
$this->response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
$this->response->setHeader('Last-Modified', gmdate('r', $modified));
$this->response->setHeader('Content-Length', $asset->getResource()->getFileSize());
$this->response->setHeader('Content-transfer-encoding', 'binary');
$this->response->sendHeaders();
@set_time_limit(86400);
$fileBuffer = 8192;
while (!feof($stream)) {
print(fread($stream, $fileBuffer));
ob_flush();
flush();
}
} finally {
fclose($stream);
}
return '';
}
这是我们的设置:
- Windows 服务器 2008 R2
- IIS 7.5
- PHP 5.5.30
我试过的:
我尝试将 memory_limit 增加到 1024Mb,增加超时,增加脚本执行时间,但我们没有从增加这些中获得任何好处。
从事件查看器中,我们在下载失败时收到很多错误消息:
Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: unknown, version: 0.0.0.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x0000000000d94b98
Faulting process id: 0x26a0
Faulting application start time: 0x01d1c3157fec8818
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: unknown
Report Id: 9ea4b22a-2f09-11e6-8366-00155d016700
Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: nativerd.dll, version: 7.5.7601.17855, time stamp: 0x4fc85321
Exception code: 0xc0000005
Fault offset: 0x000000000000f4d3
Faulting process id: 0x2170
Faulting application start time: 0x01d1c310490342e2
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: c:\windows\system32\inetsrv\nativerd.dll
Report Id: 9ea48b1a-2f09-11e6-8366-00155d016700
Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module name: iisfcgi.dll, version: 7.5.7601.17514, time stamp: 0x4ce7c6cb
Exception code: 0xc0000005
Fault offset: 0x0000000000007a47
Faulting process id: 0x28b8
Faulting application start time: 0x01d1c3016d933dec
Faulting application path: c:\windows\system32\inetsrv\w3wp.exe
Faulting module path: C:\Windows\System32\inetsrv\iisfcgi.dll
Report Id: 82a04d74-2f03-11e6-8366-00155d016700
编辑 1
看起来修改缓冲区并将其设置为 12000 有效,但不能设置为 11999。这是什么魔法?
您是否尝试过将 fread() 替换为 readfile()?它不是打开文件处理程序,而是通过 php 读取和传输文件块,而是直接将文件内容流式传输到网络服务器。
显然,将 $fileBuffer
放在 12000
可以,但不能放在 11999
... 但是为什么呢?