You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Filament用S3驱动上传图片至DigitalOcean Spaces报错

问题:Laravel Filament 上传图片到 DigitalOcean Spaces 时提示无法检查临时文件存在性

我在 Laravel Filament 项目中尝试用 S3 驱动将图片上传到 DigitalOcean Spaces,图片能成功上传到 Livewire 默认临时文件夹,但提交表单时出现错误:

Unable to check existence for: livewire-tmp/imagepath.jpg

试过多种环境配置组合,只有 public 磁盘能正常工作。相关配置代码如下:

资源文件代码

public static function form(Form $form): Form
{
    return $form
        ->schema([
            Forms\Components\Section::make('Content')
                ->schema([
                    TextInput::make('title')
                        ->label('Title')
                        ->required()
                        ->live(onBlur: true)->maxLength(255)
                        ->afterStateUpdated(fn(string $operation, $state, Forms\Set $set) => $operation === 'create' ? $set('slug', Str::slug($state)) : null),
                    TextInput::make('slug')
                        ->label('Slug')
                        ->disabled()
                        ->dehydrated()
                        ->required()
                        ->maxLength(255)
                        ->unique(Post::class, 'slug', ignoreRecord: true),
                    Textarea::make('description')
                        ->label('Description')
                        ->columnSpan('full'),
                    Forms\Components\MarkdownEditor::make('content')
                        ->label('Content')
                        ->required()
                        ->columnSpan('full'),
                    Select::make('category_id')
                        ->label('Category')
                        ->preload()
                        ->relationship('category', 'name')
                        ->searchable()
                        ->columnSpan('full')
                        ->required()
                        ->createOptionForm([
                            TextInput::make('name')
                                ->label('Name')
                                ->required()
                                ->unique(Category::class, 'name', ignoreRecord: true)
                                ->live(onBlur: true)->maxLength(255),

                        ]),
                ])->columns(),
            Section::make('Image')->relationship('image')->schema([  #this is the place
                FileUpload::make('path')
                    ->directory('posts')
                    ->disk('s3')
                    ->visibility('private')
            ])
        ]);
}

Livewire 配置

'temporary_file_upload' => [
    'disk' => 's3',        // Example: 'local', 's3'              | Default: 'default'
    'rules' => null,       // Example: ['file', 'mimes:png,jpg']  | Default: ['required', 'file', 'max:12288'] (12MB)
    'directory' => null,   // Example: 'tmp'                      | Default: 'livewire-tmp'
    'middleware' => null,  // Example: 'throttle:5,1'             | Default: 'throttle:60,1'
    'preview_mimes' => [   // Supported file types for temporary pre-signed file URLs...
        'png', 'gif', 'bmp', 'svg', 'wav', 'mp4',
        'mov', 'avi', 'wmv', 'mp3', 'm4a',
        'jpg', 'jpeg', 'mpga', 'webp', 'wma',
    ],
    'max_upload_time' => 5, // Max duration (in minutes) before an upload is invalidated...
],

.env 配置

FILESYSTEM_DISK=s3
FILAMENT_FILESYSTEM_DISK=s3

Image 模型代码

class Image extends Model
{
use HasFactory;

public function post(): BelongsTo
  {
    return $this->belongsTo(Post::class);
  }
}

解决方案

1. 检查 DigitalOcean Spaces 的 S3 磁盘配置

确保 config/filesystems.php 中 s3 磁盘的配置完全符合 DigitalOcean 要求:

's3' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'endpoint' => env('AWS_ENDPOINT'), // 如 https://nyc3.digitaloceanspaces.com
    'url' => env('AWS_URL'),
    'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
],

同时要在 Spaces 控制台配置正确的 CORS 规则,允许临时文件的读写操作:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
  </CORSRule>
</CORSConfiguration>

2. 统一临时文件与正式存储的可见性

Livewire 临时上传文件的可见性要和 FileUpload 组件保持一致,修改 Livewire 配置:

'temporary_file_upload' => [
    // ...其他配置
    'visibility' => 'private', // 与FileUpload的visibility参数匹配
],

3. 修复关联模型的文件路径处理

由于使用了 relationship('image') 关联 Image 模型,确保:

  • Image 模型的 path 字段存储的是文件的相对路径(而非完整URL)
  • 在 FileUpload 组件中添加文件名处理规则,避免路径解析错误:
    FileUpload::make('path')
        ->directory('posts')
        ->disk('s3')
        ->visibility('private')
        ->preserveFilenames() // 可选,避免文件名被哈希导致路径不匹配
    

4. 清除配置缓存

执行以下命令确保新配置生效:

php artisan config:clear
php artisan cache:clear

内容的提问来源于stack exchange,提问作者Yeasir Arafat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:05:00