基于 Laravel 6、 Guzzle 6 下载远程文件至服务器磁盘的实现
1、现在正在尝试将远程的 ZIP 文件下载至服务器。 远程文件网址:https://www.shuijingwanwq.com/wp-content/uploads/2021/07/两位老人被两只狗给撞了.wmv
2、参考:https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html#sink 。声明响应的主体部分将要保存的位置。如图1
3、参考:https://www.shuijingwanwq.com/2020/11/26/4627/ 。传入 fopen() 返回的资源将响应写入 PHP 流
/** * 下载 ZIP * @param string $uri 文件的绝对 URI * @param string $absolutePath 文件的绝对路径(下载至的目标路径) * @return void */ public function downloadZip($uri, $absolutePath) { // 实例化 HTTP 客户端 $client = new Client; // 打开即将下载的本地文件,在该文件上打开一个流 $resource = fopen($absolutePath, 'w'); $client->get($uri, ['sink' => $resource]); // file_put_contents(storage_path() . '/logs/ZipHandler-downloadZip-absolutePath-' . microtime(true) . '-' . mt_rand() . '.txt', print_r($response, true), FILE_APPEND | LOCK_EX); // 关闭一个已打开的文件指针 fclose($resource); }
4、抛出异常:fopen(E:\wwwroot\object\storage/theme_downloads/2022/05/19/1652927525.7561.1655422634.zip): failed to open stream: No such file or directory
ErrorException: fopen(E:\wwwroot\object\storage/theme_downloads/2022/05/19/1652927525.7561.1655422634.zip): failed to open stream: No such file or directory in E:\wwwroot\object\Modules\ThemeStoreDB\Handlers\ZipHandler.php:20 Stack trace: #0 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'fopen(E:\\wwwroo...', 'E:\\wwwroot\\wsho...', 20, Array) #1 E:\wwwroot\object\Modules\ThemeStoreDB\Handlers\ZipHandler.php(20): fopen('E:\\wwwroot\\wsho...', 'w') #2 E:\wwwroot\object\Modules\ThemeStoreDB\Jobs\ThemeInstallationJob.php(61): Modules\ThemeStoreDB\Handlers\ZipHandler->downloadZip('https://www.shu...', 'E:\\wwwroot\\wsho...') #3 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(36): Modules\ThemeStoreDB\Jobs\ThemeInstallationJob->handle() #4 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Util.php(37): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}() #5 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure)) #6 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure)) #7 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Container.php(590): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL) #8 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php(94): Illuminate\Container\Container->call(Array) #9 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(130): Illuminate\Bus\Dispatcher->Illuminate\Bus\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #10 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #11 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php(98): Illuminate\Pipeline\Pipeline->then(Object(Closure)) #12 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(83): Illuminate\Bus\Dispatcher->dispatchNow(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob), false) #13 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(130): Illuminate\Queue\CallQueuedHandler->Illuminate\Queue\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #14 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #15 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(85): Illuminate\Pipeline\Pipeline->then(Object(Closure)) #16 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(59): Illuminate\Queue\CallQueuedHandler->dispatchThroughMiddleware(Object(Illuminate\Queue\Jobs\RedisJob), Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #17 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Jobs\Job.php(88): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\Jobs\RedisJob), Array) #18 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(368): Illuminate\Queue\Jobs\Job->fire() #19 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(314): Illuminate\Queue\Worker->process('redis', Object(Illuminate\Queue\Jobs\RedisJob), Object(Illuminate\Queue\WorkerOptions)) #20 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(134): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\RedisJob), 'redis', Object(Illuminate\Queue\WorkerOptions)) #21 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(112): Illuminate\Queue\Worker->daemon('redis', 'default', Object(Illuminate\Queue\WorkerOptions)) #22 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(96): Illuminate\Queue\Console\WorkCommand->runWorker('redis', 'default') #23 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(36): Illuminate\Queue\Console\WorkCommand->handle() #24 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Util.php(37): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}() #25 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure)) #26 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure)) #27 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Container.php(590): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL) #28 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Command.php(134): Illuminate\Container\Container->call(Array) #29 E:\wwwroot\object\vendor\symfony\console\Command\Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #30 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Command.php(121): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #31 E:\wwwroot\object\vendor\symfony\console\Application.php(1009): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #32 E:\wwwroot\object\vendor\symfony\console\Application.php(273): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #33 E:\wwwroot\object\vendor\symfony\console\Application.php(149): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #34 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Application.php(93): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #35 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php(131): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #36 E:\wwwroot\object\artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #37 {main}
5、需要先确保目录是存在的。判断目录是否存在,如果不存在,则递归创建。
// 文件的相对路径 $directory = '/theme_downloads/' . date('Y/m/d'); // 判断目录是否存在,如果不存在,则递归创建 if (!file_exists(storage_path('app') . $directory)) { // file_put_contents(storage_path() . '/logs/ThemeInstallationJob-handle-directory-' . microtime(true) . '-' . mt_rand() . '.txt', print_r($directory, true), FILE_APPEND | LOCK_EX); Storage::disk('local')->makeDirectory($directory); } $uri = 'https://www.shuijingwanwq.com/wp-content/uploads/2022/05/theme-1.zip'; $absolutePath = storage_path('app') . $directory . '/' . microtime(true) . '.' . mt_rand() . '.zip'; // file_put_contents(storage_path() . '/logs/ThemeInstallationJob-handle-absolutePath-' . microtime(true) . '-' . mt_rand() . '.txt', print_r($absolutePath, true), FILE_APPEND | LOCK_EX); app(ZipHandler::class)->downloadZip($uri, $absolutePath);
6、下载成功。但是如果下载:.zip 的文件,提示:fclose(): supplied resource is not a valid stream resource
ErrorException: fclose(): supplied resource is not a valid stream resource in E:\wwwroot\object\Modules\ThemeStoreDB\Handlers\ZipHandler.php:27 Stack trace: #0 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'fclose(): suppl...', 'E:\\wwwroot\\wsho...', 27, Array) #1 E:\wwwroot\object\Modules\ThemeStoreDB\Handlers\ZipHandler.php(27): fclose(Resource id #1962) #2 E:\wwwroot\object\Modules\ThemeStoreDB\Jobs\ThemeInstallationJob.php(71): Modules\ThemeStoreDB\Handlers\ZipHandler->downloadZip('https://www.shu...', 'E:\\wwwroot\\wsho...') #3 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(36): Modules\ThemeStoreDB\Jobs\ThemeInstallationJob->handle() #4 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Util.php(37): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}() #5 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure)) #6 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure)) #7 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Container.php(590): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL) #8 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php(94): Illuminate\Container\Container->call(Array) #9 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(130): Illuminate\Bus\Dispatcher->Illuminate\Bus\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #10 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #11 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php(98): Illuminate\Pipeline\Pipeline->then(Object(Closure)) #12 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(83): Illuminate\Bus\Dispatcher->dispatchNow(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob), false) #13 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(130): Illuminate\Queue\CallQueuedHandler->Illuminate\Queue\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #14 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(105): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #15 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(85): Illuminate\Pipeline\Pipeline->then(Object(Closure)) #16 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\CallQueuedHandler.php(59): Illuminate\Queue\CallQueuedHandler->dispatchThroughMiddleware(Object(Illuminate\Queue\Jobs\RedisJob), Object(Modules\ThemeStoreDB\Jobs\ThemeInstallationJob)) #17 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Jobs\Job.php(88): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\Jobs\RedisJob), Array) #18 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(368): Illuminate\Queue\Jobs\Job->fire() #19 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(314): Illuminate\Queue\Worker->process('redis', Object(Illuminate\Queue\Jobs\RedisJob), Object(Illuminate\Queue\WorkerOptions)) #20 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Worker.php(134): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\RedisJob), 'redis', Object(Illuminate\Queue\WorkerOptions)) #21 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(112): Illuminate\Queue\Worker->daemon('redis', 'default', Object(Illuminate\Queue\WorkerOptions)) #22 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Queue\Console\WorkCommand.php(96): Illuminate\Queue\Console\WorkCommand->runWorker('redis', 'default') #23 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(36): Illuminate\Queue\Console\WorkCommand->handle() #24 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Util.php(37): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}() #25 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(93): Illuminate\Container\Util::unwrapIfClosure(Object(Closure)) #26 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\BoundMethod.php(37): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure)) #27 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Container\Container.php(590): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL) #28 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Command.php(134): Illuminate\Container\Container->call(Array) #29 E:\wwwroot\object\vendor\symfony\console\Command\Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #30 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Command.php(121): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #31 E:\wwwroot\object\vendor\symfony\console\Application.php(1009): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #32 E:\wwwroot\object\vendor\symfony\console\Application.php(273): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #33 E:\wwwroot\object\vendor\symfony\console\Application.php(149): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #34 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Console\Application.php(93): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #35 E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php(131): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #36 E:\wwwroot\object\artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #37 {main}
7、在尝试关闭资源之前检查资源是否仍然是资源:
// 检测变量是否为资源类型,如果是,则关闭 if (is_resource($resource)) { fclose($resource); }
8、最后自行在 Windows 10 中生成一个 zip 文件,再次测试下载,下载成功。如图2
近期评论