读Yii2框架的web返回格式化类Response

06 Aug 2018 Category: PHP

一个完整的网络请求,最后都需要一个符合协议的返回。Yii2在处理web请求之后,统一通过web/Response处理返回。错误也会经过错误处理返回一个Response。

一个Response完整的流程有哪些?

Yii2的Response

总的而言,Yii2的Response 代码逻辑结构相当清晰,而且输出内容都非常规范的遵循http协议规范。同时提供前置事件,数据准备前置事件,后置事件给开发者在不同的情况下处理额外的数据。代码在阅读起来非常明了。从头到尾,完整的看一遍,就可以完全理解。以下是Response中的两段代码。

输出内容代码
    protected function sendContent()
    {
        if ($this->stream === null) {
            echo $this->content;

            return;
        }
        set_time_limit(0); // Reset time limit for big files
        $chunkSize = 8 * 1024 * 1024; // 8MB per chunk
        if (is_array($this->stream)) {
            list ($handle, $begin, $end) = $this->stream;
            fseek($handle, $begin);
            while (!feof($handle) && ($pos = ftell($handle)) <= $end) {
                if ($pos + $chunkSize > $end) {
                    $chunkSize = $end - $pos + 1;
                }
                echo fread($handle, $chunkSize);
                flush(); // Free up memory. Otherwise large files will trigger PHP's memory limit.
            }
            fclose($handle);
        } else {
            while (!feof($this->stream)) {
                echo fread($this->stream, $chunkSize);
                flush();
            }
            fclose($this->stream);
        }
    }

没有什么特殊的。如果是简单的字符串,直接echo。主要看它处理stream的情况。

首先设置超时时间。对于读取文件流,没办法确定文件读取需要的时间,因此设置超时时间很必要。

设置最大读取长度。每个请求都需要占用一定的内存去处理数据。为了避免我限制申请内存造成php程序报内存不足,因此对于文件读取程序,必须设置读取限制。读取完及时刷新出去。

下载文件请求头设置
public function setDownloadHeaders($attachmentName, $mimeType = null, $inline = false, $contentLength = null)
    {
        $headers = $this->getHeaders();

        $disposition = $inline ? 'inline' : 'attachment';
        $headers->setDefault('Pragma', 'public')
            ->setDefault('Accept-Ranges', 'bytes')
            ->setDefault('Expires', '0')
            ->setDefault('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
            ->setDefault('Content-Disposition', $this->getDispositionHeaderValue($disposition, $attachmentName));

        if ($mimeType !== null) {
            $headers->setDefault('Content-Type', $mimeType);
        }

        if ($contentLength !== null) {
            $headers->setDefault('Content-Length', $contentLength);
        }

        return $this;
    }

想要输出一个下载文件的响应,Yii2的输出请求头中有以下内容:

设置完请求头之后就可以把内容输出。浏览器就会弹出一个下载提示框。