Laravel存储链接在生产环境无法工作

32

我正在使用storage_path来保存我的图片,并将我的存储文件夹符号链接到public_html

php artisan storage:link

在本地环境下一切正常,当我上传图片时,它会被上传到存储文件夹并在public文件夹中出现链接,但是自从我移动到生产环境和生产模式后,我的图片将被上传到存储文件夹,但public_html/storage中没有任何内容,我无法在我的前端获取它们。

代码

/config/filesystems.php

'public' => [
  'driver' => 'local',
  'root' => storage_path('app/public/'),
  'url' => env('APP_URL').'/storage',
  'visibility' => 'public',
],

.env

:这是一个文件名,通常用于存储应用程序的配置信息,例如数据库连接凭据、API密钥等。
FILESYSTEM_DRIVER=public

控制器示例

if ($request->hasFile('image')) {
  $image = $request->file('image');
  $filename = 'page' . '-' . time() . '.' . $image->getClientOriginalExtension();
  $location = storage_path('app/public/images/' . $filename);
  Image::make($image)->resize(1200, 600)->save($location);
  if(!empty($page->image)){
    Storage::delete('images/' . $page->image);
  }
  $page->image = $filename;            
}

有任何想法吗?


你没有使用public目录,而是使用了public_html。我不喜欢这个策略。在public_html中创建一个公共目录,并将url设置为env('APP_URL').'/public/storage' - Ohgodwhy
1
你需要在服务器上重新创建符号链接,因为它不会随着传输而转移。 - ATechGuy
@Ohgodwhy 抱歉,我有点困惑。1)在public_html中创建一个公共目录,我已经有了一个文件夹在我的“public_html”中,当我运行artisan命令时它就被创建了。2)我添加了'url' => env('APP_URL').'/public/storage',但没有任何变化,我仍然无法获取我的图像。 - mafortis
@ATechGuy,我该怎么做?我在我的主机上没有终端(不确定!) - mafortis
你确定应该使用 $image->getClientOriginalExtension(); 吗?这会让我在你的服务器上存储一个 .php 文件并执行其中的任何代码。 - sisve
有几种方法可以做到这一点,您可以从路由中运行相同的命令,您可以通过FTP进行操作,某些FTP程序将允许您创建符号链接。Cpanel也可以使用-> https://www.namecheap.com/support/knowledgebase/article.aspx/9561/29/how-to-create-a-symbolic-link-in-cpanel - ATechGuy
18个回答

41

我看到这个问题已经被回答了,但是我想提供另一种我认为很简单的解决方案。进入路由文件夹your-app-folder/routes/web.php并按以下方式注册新路由

Route::get('/linkstorage', function () {
    Artisan::call('storage:link');
});

然后进入您的网站www.example.com/linkstorage,它会带您到一个空白页面。就这样,存储文件夹将被创建。希望能对某些人有所帮助。


2
这是最简单的,不需要编辑路径(在许多环境中可能会有所不同)。每次迁移到生产服务器时,只需要调用此函数即可。 - Toni Tegar Sahidi
太棒了!我不知道为什么这个没有出现在官方的Laravel文档中...我想...谢谢。 - Adriana Hernández
我也无法使用...协议错误。 - ii iml0sto1
@iiiml0sto1,您也可以在公共目录中创建一个文件(例如symlink.php),并添加以下代码行 <?php symlink('/home/your-host-namespace/public_html/your-app-folder/storage/app/public', '/home/your-host-namespace/public_html/storage');,您还可以根据您的目录位置调整代码。完成后,请访问www.your-domain.com/symlink.php,这样就可以为您解决问题了。 - Chetam Okafor
@iiiml0sto1 尝试删除在开发过程中创建在公共文件夹内的任何“存储”文件夹,并重新运行上述路由。这种方法对我有效! - Dilukshan Mahendra

21
删除公共文件夹中的存储,然后在cron作业中运行此命令(一次性):
ln -s /home/public_html/storage/app/public /home/dev5/public_html/public/storage

这对我很有用,只是如果使用 Laravel Sail,你可能需要运行以下命令:ln -s /var/www/html/storage/app/public /var/www/html/public/storage - BootDev
我在 routes/web.php 文件中编写了 Artisan::call('storage:link'); 并运行了网站,然后再次在 routes/web.php 文件中注释掉了这个链接。这解决了我的问题,并自动在 public 文件夹中创建了 storage 符号链接。非常感谢。 - Kamlesh

15

我刚遇到了这个问题,以下是我如何解决它的方法,无需SSH进入服务器或运行CronJob:

对于Laravel 5+(未测试较低版本)

你可以在你的路由/控制器中使用Artisan::call() 方法来执行 Artisan 命令而不需要使用终端。

$exitCode = Artisan::call('storage:link', [] );
echo $exitCode; // 0 exit code for no errors.

10
我会尽力帮忙翻译。以下是需要翻译的内容:

我知道这是一个老旧的线程,但我们可以通过在Config/filesystem.php中进行小改动来更改它。

替换

'links' => [
        public_path('/storage') => storage_path('app/public'),
    ],

使用

'links' => [
        base_path('/public_html/storage') => storage_path('app/public'),
    ],

enter image description here

你可以查看这个仓库。我已经在其中实现了 https://github.com/ali-chaudhry/Laravel-7-Boilerplate-with-Spatie-uuid-Unishrp-filemanager-integeration

是的,这在Bigrock服务器上可以运行,谢谢Aklot man。 - Vipertecpro

9

我用以下方法解决了这个问题:

  1. 使用ssh进入项目文件夹
  2. 如果public文件夹不存在,则创建。 如果已经创建,则确保在开发中创建的存储symlink已被删除。
  3. 执行 php artisan storage:link
  4. 将创建的存储symlink移动到public_html文件夹中
  5. 完成。

我尝试了很多解决方案,只有这一个对我有效!!! - Dejan
我试图获取存储文件夹的URL。我的代码也适合获取存储图像。但它没有起作用。我使用了这个命令并检查后它就可以工作了。谢谢。 - disha
这个解决方案可行,请在将项目移动到另一台服务器时不要忘记执行此操作。 - mustofa27

6

已解决

感谢您所有的帮助,我在服务器上尝试运行php artisan storage:link,并发现我的服务器因安全原因禁用了符号链接。

因此,我将所有图像上传功能更改为将图像上传到我的public文件夹而不是storage文件夹,并且现在一切都正常工作。


4
将文件上传到公共目录并不被推荐,也不符合Laravel的标准规范。 - ahinkle
@ahinkle 将文件上传到公共网络没有任何问题,如果您的意思是其他人可以在其 URL 中加载您的资源并使用您的源代码,则您始终可以通过代码或使用 Cloudflare 链接保护来限制其他来源对资源的访问。 - mafortis
1
是的,这取决于我们使用的主机/服务器限制,不是所有事情都在我们掌控之中。而且,没有人在寻求点赞,我们在这里为了解决方案。祝你好运。 - mafortis
1
@ahinkle,如果由于某些原因我们无法使用符号链接,您建议采取什么措施? - Lamar
@Lamar,如我所提到的,使用公共文件夹(即public_html),直接在那里上传您的文件,并使用public_path()。 - mafortis
显示剩余5条评论

5

通过public_path更改storage_path设置

'public' => [
  'driver' => 'local',
  'root' => public_path('app/public_html/'),
  'url' => env('APP_URL').'/storage',
  'visibility' => 'public',
],

if ($request->hasFile('image')) {
  $image = $request->file('image');
  $filename = 'page' . '-' . time() . '.' . $image->getClientOriginalExtension();
  $location = public_path('app/public_html/images/' . $filename);
  Image::make($image)->resize(1200, 600)->save($location);
  if(!empty($page->image)){
    Storage::delete('images/' . $page->image);
  }
  $page->image = $filename;            
}

如果那个方法不起作用,你可以尝试以下方法:
$path = base_path().'/../public_html/images'; 

1
这个 /public 目录是你放置资源的同一个目录吗?还是它只是 /storage 文件夹里面的一个神奇文件夹? - Lamar

5

以下翻译仅供参考:

本答案适用于仍然遇到问题的人

步骤1

public文件夹中删除storage链接。

步骤2

授予storage文件夹权限。

chmod -R 775 storage/

步骤三

创建符号链接

php artisan storage:link

那个真的很有效! - undefined

3

我也遇到了同样的问题。当你在服务器上开始使用生产环境时,必须重新初始化/运行命令php artisan storage:link。确保您的Web主机提供SSH访问或使用脚本文件。

Artisan::call('storage:link', []);

否则执行命令。我使用的是 Laravel v8+ 和 Livewire。


3
您也可以删除您的文件夹storage:link,然后在主机上打开终端并输入命令php artisan storage:link。如果您的托管支持符号链接,则它将起作用。

这是一个很好的答案。我在我的服务器上看到符号链接被禁用了,所以我启用了它,然后运行了storage:link命令,但是没有任何效果,所有的链接仍然是404。然后我看到了这个答案,将存储文件夹从PUBLIC中删除,重新运行命令,然后就成功了! - Saif Manwill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接