Using PHP to stream a file to client

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
vasoftball5
Forum Newbie
Posts: 3
Joined: Mon Jul 08, 2002 9:49 am
Location: VA, USA

Using PHP to stream a file to client

Post by vasoftball5 »

Ok, I've been through the board and found nothing on this topic. It's somewhat related to security and hiding the "true" location of a file.

I have a site which has documents on it. The docs are "classified". The site allows an "authenticated" user (just call them that for now) to download documents affiliated with the user. The problem is this: the URL of the document is cached in the browser's "history" list. This provides a direct link to the document. Authentication cannot be performed on this request. Normally, this poses no problem, but if an executive happens to be at a "public" machine and downloads the file, the cached link is available to unauthorized persons.

What I want to do is create a script that will be called, let's call it "docView.php". This script is passed form data which is used to determine the validity of the request. The script will then open the requested document and stream the contents to the browser. The link to this script is cached - not the actual location of the document.

For those who are new to this world - using

header("Location: $filename");

won't work. This causes a 302 to be sent to the browser, which is a client-side redirect. The location of "$filename" is cached.

So... what I'm trying to perform is equivalent to a server-side redirect. The browser will know nothing of the actual contents of the document.

To further complicate.... I've streamed the file back preceded by a call to

header ("Content-type: application/octet-stream; name=$filename");

This is SUPPOSED to cause the browser to prompt the user to save the file and provide $filename as the suggested name of saving. It doesn't work. The File Save dialog appears with the name of my script ("viewDoc.php") instead.

If streaming is the right solution, then what is the Content-type that should be used so the browser opens the file using the correct "helper application"? Can PHP perform a server-side redirect?

HELP!!!!!!

gm
User avatar
llimllib
Moderator
Posts: 466
Joined: Mon Jul 01, 2002 2:19 pm
Location: Baltimore, MD

Post by llimllib »

As for the suggested filename, even if you got that to work, it's a hack - the HTTP 1.1 spec contains nothing of the sort:
14.17 Content-Type

The Content-Type entity-header field indicates the media type of the
entity-body sent to the recipient or, in the case of the HEAD method,
the media type that would have been sent had the request been a GET.

Content-Type = "Content-Type" ":" media-type

Media types are defined in section 3.7. An example of the field is

Content-Type: text/html; charset=ISO-8859-4
As for the addresses being cached, why not just have a form where authenticated users select the doc they want, and then it is 'post'ed to the server (as opposed to 'get'ed)?
vasoftball5
Forum Newbie
Posts: 3
Joined: Mon Jul 08, 2002 9:49 am
Location: VA, USA

Posting to the page....

Post by vasoftball5 »

Did that one already. As long as the request has the target URI containing my document name, the link is stored in the browser's history. This happens whether I use an HREF, form POST, form GET, or Location header.

As for HTML spec - the specification clearly indicates the ability to send a suggested filename. The Content-type header has a Name parameter. This is explained in the context of MIME mail attachments. In HTML, you can use a Content-Disposition header with the name parameter. I haven't tried this one yet - I'm about to do it to see if I can get that to work. The "hack" about this isn't to try to get the browser to use my filename, but having my filename "xxxx.doc" will "suggest" to the user that the file should be saved with a like extension. Thus, the local system will recognize the byte stream as the proper application file type.

Yes - it's still a "hack" in that the user can save the file as "xxx.bazzfazz" and screw everything up. I have to put a little trust in them if file-saving is required.
User avatar
llimllib
Moderator
Posts: 466
Joined: Mon Jul 01, 2002 2:19 pm
Location: Baltimore, MD

Post by llimllib »

both MIME attachments and HTTP have a content-type header, but I believe that they are entirely different. The headers you are sending are HTTP headers, and they should follow the exact specification that I just sent you (assuming browsers follow the spec - certainly not always true, but it's what you should try to follow).

Also, I didn't mean "hack" in a negative sense - hacks that work well can be good things :D .

And, finally, if you post the name of the doc, it's not in the URI - it's passed after the http headers, but you're right, it can still be cached. What you can do to prevent refreshing is add a session variable to the user, check it when you load the page, and if it's the same, send them back to wherever you want.
User avatar
Wayne
Forum Contributor
Posts: 339
Joined: Wed Jun 05, 2002 10:59 am

Post by Wayne »

what about putting an .htaccess file on the folder with a php wrapper file.

Any file requested will call the wrapper file, which would do your user validation and only then load the file. It wont matter if the URL is cached as any hit on the folder will be handed off to the php script for validation.
User avatar
massiveone
Forum Commoner
Posts: 29
Joined: Tue Jun 18, 2002 4:39 pm
Location: Canada
Contact:

The ultimate solution

Post by massiveone »

Using php with mysql to store your filelinks is the best method. If you create an equation that changes the download url every x many seconds , i made mine 300 it works great no one can steal your links plus you can easily change them.
if you want to see an example go to http://www.crackstore.com and go to the tools section
move your mouse over a file and check the url to download, then refresh the page and you will see it is different.
also if the timeout expires a file is still downloaded its just a dummy.
if you want to know more on how i did this shoot me an email
:D
Post Reply