An endpoint returns valid PDF data, but the browser opens it instead of downloading it or suggests an unhelpful filename. The PDF generator may be fine: HTTP response metadata also shapes the download experience.
1. Separate content type from handling
Content-Type describes the data format, while Content-Disposition suggests handling and a saved filename. Illustrative headers:
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
attachment requests download handling; inline requests normal processing for the media type, such as a supported PDF viewer. Do not promise identical dialogs across browsers: user settings and client capabilities still matter.
2. A download name is not a server path
The URL can be /documents/42/download while the suggested name is report.pdf. There is no need to reveal internal storage directories.
RFC 6266 treats server-supplied names as advisory. Clients need safe handling of path components, control characters and special names. Servers should generate names from controlled data rather than concatenating raw user input into headers.
3. Unicode names and a fallback
Send an ASCII fallback with filename and a UTF-8 name with filename*. For “báo cáo.pdf”:
Content-Disposition: attachment; filename="bao-cao.pdf"; filename*=UTF-8''b%C3%A1o%20c%C3%A1o.pdf
Clients understanding both prefer filename*. The portion following UTF-8'' uses the extended-parameter encoding; this is not an instruction to encode the whole download URL. Prefer a framework's download-response API over manual header construction and inspect its output.
A useful name does not validate the payload. An HTML error saved as report.pdf is still not a PDF. Check status, media type and actual content.
4. Authorization is separate
attachment does not authorize access or encrypt documents. The endpoint must verify the caller's permission for the specific document. An unpredictable identifier is no substitute.
For private data, review caching, logs and URL-sharing practices. Avoid secrets in filenames. This header also does not control how recipients manage files after downloading them.
5. Test the actual download path
- Use a nonsensitive sample in a test environment.
- Inspect the final file response in DevTools Network, not only a redirect.
- Check status, Content-Type, Content-Disposition and the suggested saved name.
- Test ASCII, accented and space-containing names on supported clients.
- Open the file with an appropriate application to ensure it is not an error page.
If frontend JavaScript fetches data and creates the download itself, inspect its filename logic separately. A server header does not mean every client implementation automatically uses it. Direct navigation and scripted downloading may require different tests.
6. Handoff checklist
- A meaningful name without internal paths.
- A media type matching the actual payload.
- Tested UTF-8 names with a fallback.
- Authorization before document delivery.
- Errors not packaged as successful downloads.
A complete download feature combines correct content, permissions and delivery behavior. Content-Disposition supports the last part without replacing the others.




No comments yet. Be the first to share your thoughts.