简体   繁体   English

使用PHP在IIS中文件下载随机失败

[英]File downloads are randomly failing in IIS with PHP

We have a website that streams files to our customers. 我们有一个网站,可将文件流式传输给客户。 Now, we started having files bigger than 300Mb and for no apparent reasons, the downloads are randomly failing. 现在,我们开始拥有大于300Mb的文件,并且没有明显的原因,下载随机失败。 We get a "the download was interrupted" error. 我们收到“下载中断”错误。

We logged in to the server and figured out that the PHP processes were sometimes closing when a download would start but there's nothing significant either in the event viewer or in the logs. 我们登录到服务器,发现下载开始时PHP进程有时会关闭,但事件查看器或日志中没有任何重要意义。

Here's the code that delivers the downloads: 这是提供下载的代码:

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 '';
    }

Here's our setup: 这是我们的设置:

  • Windows Server 2008 R2 Windows Server 2008 R2
  • IIS 7.5 IIS 7.5
  • PHP 5.5.30 PHP 5.5.30

What I tried: 我试过的

I tried to increase the memory_limit to 1024Mb, to increase the timeout, to increase the script execution time and we didn't get any benefits from increasing those. 我试图将memory_limit增加到1024Mb,以增加超时时间,以增加脚本执行时间,而增加它们并没有带来任何好处。

From the event viewer, we are getting a lot of errors when the downloads fail: 从事件查看器中,下载失败时会遇到很多错误:

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

Edit 1 编辑1

It looks like modifying the buffer an putting it at 12000 works, but not at 11999. What kind of sorcery is this? 看起来好像修改缓冲区并使其在12000起作用,但在11999却没有。这是什么魔术?

Have you tried replacing fread() with readfile()? 您是否尝试过用readfile()替换fread()? Instead of opening a file handler, reading and transmitting chunks of the file through php, it directly streams the file contents to the webserver. 它无需打开文件处理程序,而是通过php读取和传输文件块,而是直接将文件内容流式传输到Web服务器。

http://php.net/manual/de/function.readfile.php http://php.net/manual/de/function.readfile.php

显然,将$fileBuffer12000可以,但是不能设置为11999 ...但是为什么呢?

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

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