Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I want to serve invoices for download. Currently I'm using a simple numbering scheme (invoice-01.pdf, invoice-02.pdf, and so on). I know that I could use hashes instead to obscure the data.

Is it also possible to use PHP and serve the invoices by not directly having the user point to them?

share|improve this question
Yes. How about "invoices.invalid/…; ? – mailq Sep 29 '11 at 13:19
up vote 15 down vote accepted

There is even an example of this on

// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf

Or expand that a bit with

if ( can_this_file_be_downloaded() ) {
  header('Content-type: application/pdf');
  header('Content-Disposition: attachment; filename="invoice.pdf"');
} else {
  die("None shall pass");
share|improve this answer

Sam has the answer. Also put them in a directory with .htaccess:

Authname Private
AuthType basic
require user noadmittance

That will keep out direct access if they know the url. You can still read it from your PHP script with readfile().

share|improve this answer
Thanks for the good advice. – Frank Vilea Sep 29 '11 at 13:52
Because of your suggestion I just had another idea: I put all the invoices outside of the www folder. :-) Thanks again! – Frank Vilea Sep 29 '11 at 14:01
Yeah even better! – Charlie Sep 29 '11 at 14:01

I found for this excellent guide: How to serve big files through PHP.

Especially useful is the lighttpd trick - If your PHP happens to run under lighhtpd, script only needs to set "X-Sendfile" header, and lighttpd will read and send the file for you (and it well knows how to send files).


Lighttpd has this feature and there is a mod_xsendfile for Apache2.

(Quoted from NginX documentation)

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.