getPathname(); list($bucket, $key) = explode('/', substr($sourceFilename, 5), 2); $filename = $this->options['source_converter']->convert($sourceFilename); $this->createDirectory($filename); // Some S3 buckets contains nested files under the same name as a directory if (is_dir($filename)) { return false; } // Allow a previously interrupted download to resume if (file_exists($filename) && $this->options['resumable']) { return new ResumableDownload($this->options['client'], $bucket, $key, $filename); } return $this->options['client']->getCommand('GetObject', array( 'Bucket' => $bucket, 'Key' => $key, 'SaveAs' => $filename )); } /** * @codeCoverageIgnore */ protected function createDirectory($filename) { $directory = dirname($filename); // Some S3 clients create empty files to denote directories. Remove these so that we can create the directory. if (is_file($directory) && filesize($directory) == 0) { unlink($directory); } // Create the directory if it does not exist if (!is_dir($directory) && !mkdir($directory, 0777, true)) { $errors = error_get_last(); throw new RuntimeException('Could not create directory: ' . $directory . ' - ' . $errors['message']); } } protected function filterCommands(array $commands) { // Build a list of all of the directories in each command so that we don't attempt to create an empty dir in // the same parallel transfer as attempting to create a file in that dir $dirs = array(); foreach ($commands as $command) { $parts = array_values(array_filter(explode('/', $command['SaveAs']))); for ($i = 0, $total = count($parts); $i < $total; $i++) { $dir = ''; for ($j = 0; $j < $i; $j++) { $dir .= '/' . $parts[$j]; } if ($dir && !in_array($dir, $dirs)) { $dirs[] = $dir; } } } return array_filter($commands, function ($command) use ($dirs) { return !in_array($command['SaveAs'], $dirs); }); } protected function transferCommands(array $commands) { parent::transferCommands($this->filterCommands($commands)); } }