I have a webapp which reads from the php://input and it streams from it and than stores that data in a new file, however, because of this, a person might upload a file partially and it'll still be saved, so my question is: how can I make sure that every file which was uploaded this way was infact fully uploaded?
I guess it is something to do with content-length, but I haven't found any resources which talk about this.
Yes, you should be able to retrieve the content length from the HTTP header. After that it is just binary data. You cannot determine if the file was fully uploaded from the file information on the file system, of course.
See also: Get size of POST-request in PHP
Related
I'm trying to serve a file for download to a user, and I'm having trouble with fpassthru. The function I'm using to download a file is:
http://pastebin.com/eXDpgUqq
Note that the file is successfully created from a blob, and is in fact the file I want the user to download. The script exits successfully, and reports no errors, but the file is not downloaded. I can't for the life of me think what's wrong.
EDIT: I removed the error suppression from fopen(), but it still reports no error. Somehow the data in the output buffer is never being told to be downloaded by the browser.
I tried your code (without the blob part), and it worked fine. I can download a binary file. Based on my experience, here are something to check:
Has the file been completely saved before you initiate the reading? Check the return value of file_put_contents.
How large is the file? fpassthru reads the whole file into memory. If the file is too large, memory might be insufficient. Please refer to http://board.phpbuilder.com/showthread.php?10330609-RESOLVED-php-driven-file-download-using-fpassthru for more information.
Instead of downloading the file to local server (reading the whole file into server’s memory, and letting the client download the file from the server), you can create an SAS URL, and simply redirect the browser to the URL. Azure will take care of download automatically. You many want to refer to http://blogs.msdn.com/b/azureossds/archive/2015/05/12/generating-shared-access-signature-sas-using-php.aspx for a sample.
I was able to download the file by passing a stream obtained with the Azure API directly to fpassthru, without creating a file. Unfortunately, I can't show the code because it belongs to a project that I have finished working on and the code is no longer available to me.
First 3 bytes of FLV file are signature "FLV". Now my question:
Is there any possibility in PHP to handle file uploads so that we can hook into the input stream of uploading file and check the first 3 bytes?
The scenario is i don't want the complete file to be uploaded (in temporary folder) and then check if the file is FLV or not, i just want to read first few bytes of uploading stream and if it is not "FLV" then return/exit.
The file needs to be uploaded by HTML based form. Can't rely on javascript,flash uploader or any client side validation workarounds i.e. need a pure PHP based solution.
I already know that PHP does not hand over control to our script until it finishes uploading file in temporary folder and populating global variables i.e $_POST $_GET $_FILES etc.
Also there is a somewhat similar question here:
How to upload a file byte by byte in php
but answers does not satisfy my requirement/question.
Any ideas are really appreciated!
Thanks
First, set session.upload_progress.enabled in your php.ini.
Then, use session.upload_progress to track how many bytes have uploaded. Once you have reached the minimum threshold, check the temporary file being uploaded, it will be in $_SESSION[unique_key]['files'][0]['tmp_name']. If the file doesn't match, set $_SESSION[unique_key]["cancel_upload"] to TRUE, and the file will be rejected.
To get unique_key:
ini_get("session.upload_progress.prefix") . $_POST[ini_get("session.upload_progress.name")];
If the above does not work (I haven't tested it), then your only recourse would be to create your own custom handler for PHP either as an Apache module (or better, as a custom CGI application). There you could do your filtering.
#burhan-khalid provided a more up to date and correct answer above.
Short Answer is no with your constraints.
You can not access that file with PHP until it has been uploaded to the server. After it is uploaded you can read it but not before, at least not without some type of client side software that would allow you to stream it to PHP instead of the normal form submission.
I have a form that uses a hidden iframe to submit a file to a script that changes the file and then returns the changed file. I found that I don't actually have to save the file anywhere if I just do something along the lines of echo file_get_contents(tmp);, where tmp is the path of the file uploaded to the apache tmp directory.
The script also does: header("Content-type: application/octet-stream") so that when the iframe loads, the user is prompted for download. I would like to know, on the client side, if everything went alright with the server. It's not an XMLHttpRequest, so I can't check the headers, and the only thing returned is the file itself.
Is there some way to return some json before streaming the file? Or, is there a way to check the headers of an iframe?
Currently, I've been setting a cookie with the server and checking every half a second with javascript to see if the cookie was set. I would prefer a less hacky solution than this though.
If you stream JSON before the file, the MIME header will be invalid and the browser will not be able to download the file.
In terms of checking "if everything went alright with the server", why wouldn't you be determining this on the server, rather than going round-trip to the client and back again? Allowing it to error-out on the client smells of bad design.
How could I extract the METADATA / METAINFO / everything that would describe the REMOTE FILE without downloading it in the first place?
do you have some snippets in PHP?
how about in cURL?
or any language?
thanks
You can't get all the metadata from a file without downloading the entire file, as you have no way of knowing how much of the file you need before you've captured its metadata block, some file formats store metadata at the end of the file (meaning you'll need the entire file anyway), some files don't have any metadata embedded in them at all, and so on.
If you do a HEAD request, you will usually be able to get some basic metadata on the file in question in the form of the content-type and content-length headers returned by the server, but this is typically limited to the MIME type and the file size (and if you're dealing with a script that serves the file and that script doesn't set the necessary headers, you might not even get that).
Is it possible in PHP to configure it to somehow not save files to disk at all? As a matter of fact, the best thing would be to get the script going before even reading the entire POST body. (Keeping my hopes high ;))
You can turn off file uploads via a configuration setting in PHP.
http://php.net/manual/en/ini.core.php#ini.file-uploads
PHP needs a place to temporarily store the files content for you to be able to interact with it through PHP - although, you don't have to do anything else other then access the temporary file to get the data:
$content = file_get_contents($_FILES["user_file"]["tmp_name"]);
From here on you can manipulate with the files content without having to move the uploaded file to another location before accessing it.
You can use HTTP PUT requests to directly upload a file. PHP will not handle the upload directly (e.g. set it up in $_FILES). Instead, you have to read the raw bytes from the php://input pseudo-url and from there can do whatever you want.
There's some details and examples here.