Nice url for pdf download

Hi there,

I have a PDF that the client is supposed to upload via the panel and that the site users can open into a new tab. Since apparently the PDF gets copied to the media folder, the resulting url when opening the pdf is something like this:

http://mydomain.com/media/pages/home/872171345-1576108074/pdf-filename.pdf

I would prefer the pdf to appear under a much simpler url, ideally something like

http://mydomain.com/pdf-filename.pdf

Is it somehow possible to set it up this way, while still allowing the panel upload?

Thanks!

I don’t know if that’s possible tbh, but you might want to keep it as is because it’s really nice to cache-bust updates, especially with those pesky pdf files.

You could serve the file from the content folder by creating a custom file::url component, but I’m not sure this works with individual files.

You would still get the complete path starting from the content folder in the URL though.

I haven’t tried that yet, maybe it would be possible to serve that particular file via a route.

I made a quick test:

  'routes' => [
    [
      'pattern' => 'test.pdf',
      'action'  => function () {
        if ($file = site()->file('test.pdf')) {
            return new Response($file->read(), 'application/pdf');
        }
        return go('error');
      }
    ]
  ],

Then in your template, point to this route instead of using the file url.

What do you mean by this? How do I “point” to a route? Could you give me a snippet as an example?

<a href="<?= $site->url() . '/' . $file->filename() ?>"><?= $file->filename() ?></a>

Note that in the example above, this will only work if your file is called test.pdf, you would have to adapt the route to your real filename and if it’s not only that one file, you have to make the route dynamic.

Sorry, I don’t quite follow. Where and how do I need to define the $file variable that you mention in the snippet above?

Where you use your file, replace $file with whatever variable/code you use when you call the file. You will usually do something like this:

<?php if ($file = $page->file('test.pdf')) {
  echo $file->url();
} ?>

In this case replace $file->url() with the code above.

Ok, I think I got the template part set up correctly. However, the routing option that you suggested above does not seem to work. I always get taken back to my home page instead of having it open the pdf.

I have a default.php template set up that contains the line <?php go('home') ?>, I wonder if this overwrites the routing somehow?

That should not interfere with other templates. Please post your code, config and template.

Config code:

'routes' => [
    [
      'pattern' => 'test.pdf',
      'action'  => function () {
        if ($file = site()->file('test.pdf')) {
          return new Response($file->read(), 'application/pdf');
        }
        return go('error');
      }
    ]
  ]

Template code:

  <?php $file = $site->homePage()->files()->template('pdf')->first() ?>
  <a href="<?= $site->url() . '/' . $file->filename() ?>"><?= $file->filename() ?></a>

And the file is really called test.pdf? But the route searches for the file in site() not in the home page… So that doesn’t make sense and you have to change it to your location.

Ah, okay. I thought site()->file('test.pdf') would globally search and return the given file. Sorry for the confusion. Changed the route now to site()->homePage()->file('test.pdf') and it works.

Thanks a lot!