没有不值得去解决的问题,也没有不值得去学习的技术!

How to Download Remote Files to Server Disk with Laravel 6 and Guzzle 6

Reference: https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html#sink . Declares the location where the body of the response will be saved

1. I am now trying to download a remote ZIP file to the server. Remote file URL: https://media.shuijingwanwq.com/2021/07/两位老人被两只狗给撞了.wmv

2. Reference: https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html#sink . Declares the location where the body of the response will be saved. See Figure 1.

Reference: https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html#sink . Declares the location where the body of the response will be saved
Figure 1

3. Reference: Pass the resource returned by fopen() to write the response to a PHP stream

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. Exception thrown: fopen(E:\wwwroot\object\storage/theme_downloads/2022/05/19/1652927525.7561.1655422634.zip): failed to open stream: No such file or directory

Plaintext

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. I need to ensure that the directory exists first. I check whether the directory exists, and if it does not, I create it recursively.

PHP

        // 文件的相对路径
        $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://media.shuijingwanwq.com/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. The download succeeds. However, when downloading a .zip file, it prompts: fclose(): supplied resource is not a valid stream resource

Plaintext

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. Before attempting to close the resource, check whether the resource is still a resource:

Plaintext
        // Check if the variable is of type resource, and if so, close it
        if (is_resource($resource)) {
            fclose($resource);
        }

8. Finally, I manually generated a zip file in Windows 10 and tested the download again; the download succeeded. See Figure 2.

Finally, manually generated a zip file in Windows 10 and tested the download again; the download succeeded
Figure 2

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系