Answer for 2023
This is a frustrating problem for developers who want to generate a PDF inside the browser with something like pdf-lib while retaining control over the default filename offered to the user when they click the download/save button on the browser's built-in PDF viewer.
Back story
I wasted a bunch of time trying to get PDF.js to work in Svelte so it looks like the the default PDF viewer with just the download button overridden. I had one problem after the other. Everything seemed stacked against me and there were old Stack Overflow answers and blog posts casually mentioning their project that uses PDF.js to display PDFs. Things had changed (like the introduction of a top-level await that Svelte doesn't like and a change in philosophy about the release of the default viewer's source code). Was I really going to have to generate the files on the server just so I have control over the filename? That's not acceptable.
Overview
Thankfully, you can now solve this problem with the Cache API in combination with the Service Worker API. They are widely supported by modern browsers, so there shouldn't be any issues in terms of compatibility. IE doesn't support it, obviously, but that's not really worth mentioning.
Unfortunately, this won't work well in Chromium-based browsers because of a years-old bug
This technique allows you to leverage browser-based rendering while maintaining control over the filename with the caveat that Chromium will only download the file directly from the server. Please star the bug report if you want to see this fixed in Chromium.
Cache API
Basically, you add the document to a cache and assign it a URL on your server that is won't get in the way of any other files, then set an iframe's src to the URL once the cache finishes accepting it. That stores it where your service worker can find it and tells the browser to go looking for it there. Since you define the URL, you also control the filename (it's the last segment of the pathname).
Service Worker API
Then you create and register a service worker that checks the cache to see if the file exists before fetching it from the Internet. If it's in your cache, it's because you put it there, so don't worry about it getting confused with random files. When the browser goes looking for the file that you stored a moment ago, it'll find and return it as if you downloaded it off the Internet.
Conclusion
Service workers are easy to register in SvelteKit just by creating a file in the correct location, but it really doesn't take much to create and register one with any other framework. You just have to keep in mind that the browser will try to hang onto the service worker, forcing you to clear your site data when you want to make changes to it. So it's best to avoid putting code in there that might change frequently.