diff --git a/.gitignore b/.gitignore index c422267..42cd73d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1 @@ -composer.phar -/vendor/ - -# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file -# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file -# composer.lock +/vendor/ \ No newline at end of file diff --git a/README.md b/README.md index 647cb04..57cc1b6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,39 @@ # file-serving Serve files to the browser that are not available directly + +## Installation +```bash +composer require gisostallenberg/file-serving +``` + +## Usage example +```php +serve(); // will server http://example.com/serve-it/example.txt when ../serve-me/example.txt exists, gives a 404 otherwise +``` + +```php +getResponse(); // do not serve yet + +if ($response->getStatusCode() === Response::HTTP_NOT_FOUND) { + $fileserver = new FileServer('../serve-other-dir/', 'serve-it/'); // check another directory + $response = $fileserver->getResponse(); +} + +$response->send(); +``` + +## Credits +Niels Nijens (https://github.com/niels-nijens/) \ No newline at end of file diff --git a/composer.json b/composer.json index 87c8497..d926896 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,8 @@ "description": "Serve files to the browser that are not available directly", "type": "package", "require": { - "symfony/http-foundation": "^3.0" + "php": "^5.3.9", + "symfony/http-foundation": "^2.8|^3.0" }, "license": "MIT", "authors": [ diff --git a/composer.lock b/composer.lock index 0d1be90..68d85e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "eae6584cb4286aad304a3ff8982147f4", - "content-hash": "cfde36da2fc2eb51eb3cc8cbe7efd8f6", + "hash": "0d73e04b49b07c4b76f2414d499ccf90", + "content-hash": "4d92e58c0acc5a7dc9a6db7f8bfec86e", "packages": [ { "name": "symfony/http-foundation", @@ -66,6 +66,8 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": "^5.3.9" + }, "platform-dev": [] } diff --git a/src/FileServer.php b/src/FileServer.php index 457c4dd..5d04360 100644 --- a/src/FileServer.php +++ b/src/FileServer.php @@ -2,10 +2,109 @@ namespace GisoStallenberg\FileServing; +use DateTime; +use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; class FileServer { - + /** + * The path to serve from. + * + * @var string + */ + private $from; + + /** + * The server path to serve. + * + * @var string + */ + private $to; + + /** + * The request object. + * + * @var Request + */ + private $request; + + /** + * The base path to find files. + * + * @var string + */ + private $basePath; + + /** + * Constructor. + * + * @param string $from + * @param string $to + * @param Request $request + */ + public function __construct($from, $to, Request $request = null) + { + $this->from = $from; + $this->to = $to; + + if (is_null($request)) { + $request = Request::createFromGlobals(); + } + $this->request = $request; + + $this->basePath = $this->request->server->get('DOCUMENT_ROOT'); + } + + /** + * Creates a new instance. + * + * @param string $from + * @param string $to + * @param Request $request + * + * @return \static + */ + public static function create($from, $to, Request $request = null) + { + return new static($from, $to, $request); + } + + /** + * Creates the response object. + * + * @return Response + */ + public function getResponse() + { + $requestPath = parse_url($this->request->server->get('REQUEST_URI'), PHP_URL_PATH); + + $filePath = $this->basePath.$this->from.substr($requestPath, strlen($this->to)); + + if (is_file($filePath)) { + $file = new File($filePath); + $response = Response::create() + ->setExpires(new DateTime('+1 week')) + ->setLastModified(DateTime::createFromFormat('U', $file->getMTime()));; + + if ($response->isNotModified($this->request)) { + + return $response; + } + + $response->headers->set('Content-Type', $file->getMimeType() ?: 'application/octet-stream'); + return $response->setContent(file_get_contents($file->getPathname())); + } + + return Response::create('', Response::HTTP_NOT_FOUND); + } + + /** + * Serves the file. + */ + public function serve() + { + $this->getResponse()->send(); + } }