/** * Create an instance from a file. * @param string $file a path to a file * @param string $name optional name to serve the file with * @param string $hash optional string to use as ETag * @param string $cached optional strtotime expression used for caching validity * @return \vakata\http\Response the response instance * @codeCoverageIgnore */ public static function fromFile($file, $name = null, $hash = null, $cached = null) { $res = new self(); $name = $name ?: basename($file); $size = filesize($file); if ($name) { $extension = substr($name, strrpos($name, '.') + 1); if ($extension) { $res->setContentTypeByExtension($extension); } $res->setHeader('Last-Modified', gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT'); if ($hash !== null) { $res->setHeader('ETag', $hash); } if ($cached !== null) { $res->cacheUntil($cached); } $disposition = in_array(strtolower($extension), ['txt', 'png', 'jpg', 'gif', 'jpeg', 'html', 'htm', 'mp3', 'mp4']) ? 'inline' : 'attachment'; $res->setHeader('Content-Disposition', $disposition . '; ' . 'filename="' . preg_replace('([^a-z0-9.-]+)i', '_', $name) . '"; ' . 'filename*=UTF-8\'\'' . rawurlencode($name) . '; ' . 'size=' . (string) $size); $res->setHeader('Content-Length', (string) $size); } $res->setBody(fopen($file, 'r')); return $res; }