Files section in file blueprint

Hello forum,

I thought it would be clever to add a files section to a file blueprint in order to be able to provide alternative files (in this case for a video). That way I could upload a main file (e.g. a WebM video) and provide one or multiple fallbacks (e. g. an MP4 video)—on a per-file basis.

# blueprints/files/video.yml

sections:
  alternativeFiles:
    type: files

When I set this up and don’t provide the parent option, I see an error when trying to upload a file:

No route found for path: "pages/projects+test-123/files/video.mp4/files" and request method: "POST"

When I look at the route it looks like Kirby is treating the file like a page and tries to access its files.

So I tried to set the section parent to the main file’s parent by adding parent: file.parent to the blueprint. Now, instead of the files section, I see an error in the panel (I replaced the private path with xxx):

Kirby\Cms\File::is(): Argument #1 ($file) must be of type Kirby\Cms\File, Kirby\Cms\Page given, called in xxx/kirby/config/sections/files.php on line 115.

Therefore I tried it with parent: page.parent and get this error instead:

The parent for the query "page.parent" cannot be found in the section "alternativeFiles"

Should this be possible? Am I doing something wrong? I think it would be a neat solution for the fallback / alternative file type problem.

Actually… now I noticed that I would of course see the alternative files of all files that were uploaded in the same directory, which is not really a gain. Probably I wont’t get around creating a subfolder for each file that can contain alternative files as well.

It would probably make sense to use a files field instead of a section?

Yes, that works—thank you!

I would have preferred the files section so that the files could have been managed (i. e. deleted) in place. Now it’s only possible to delete a file if you select it in the field and click on it afterwards. Still works though.

If you want a section, you could try it with a custom api route.

I tried this and seems to work, but I don’t know if this is fool-proof (and haven’t tested renaming and stuff):

    'api' => [
        'routes' => [
            [
                'pattern' => 'pages/(:all)/files/(:any)/files',
                'method' => 'POST',
                'action'  => function ($path) {
                    $path = str_replace('+', '/', $path);
                    return $this->upload(function ($source, $filename) use ($path) {
                        return $this->page($path)->createFile([
                            'content' => [
                                'sort' => $this->requestBody('sort')
                            ],
                            'source'   => $source,
                            'template' => $this->requestBody('template'),
                            'filename' => $filename
                        ]);
                    });
                }
            ]
        ]
    ]
1 Like

Nice, this looks clever. I will come back to it when I can spare some time, because this is a recurring problem. For now the files field will do.