4

We have PHP code on a server that receives files into $_FILE and then stores them based on user/security considerations.

On the client, we can currently send the file to the server as-is or we would like to process the file locally (in memory in js in the browser) and then deliver the file to the server. We can POST the processed file to the server using JSON, however there are issues with that.

We would much prefer to send the contents of the client's javascript variable to the server to be received in $_FILE. (We cannot assume client will have the ability to save the file locally.) Do we have to imitate a FORM submission somehow?

How to we send a javascript variable to be received as a PHP $_FILE?

Thanks!

UPDATE Blob definitely appears to be the right direction, but we are noticing that the Blob size is coming out 50% larger than the file that goes in to it. The file in $_FILE is also 50% larger. We have tried overriding the file type at Blob creation, based on other posts such as BlobBuilder ruins binary data, however it hasn't fixed the 50% increase in size. We are setting the Blob file type based on the drag and drop file type we receive. For example, we upload a 900K PDF file. Type was something like 'application/pdf'. The resultant blob was like 1,400K. Also tried with PNG.

Community
  • 1
  • 1
Mark Kasson
  • 1,492
  • 15
  • 24

4 Answers4

3

If the client supports Blob and XHR2 (FormData), then you're gold. Supposing that your data is kept in a string data, all you have to do is

// Set the file media type appropriately
var blob = new Blob([ data ], { type: "image/png" });

var formData = new FormData();
formData.append("theFile", blob, "filename.png");

var xhr = new XMLHttpRequest();
xhr.open("POST", "/destination");
xhr.send(formData);
xhr.onload = function() {
    // ...
};

UPDATE: if your client doesn't support XHR2, there is a way to send files using AJAX only, although it's a bit complicated.

Basically, you have to mimic a multipart/form-data request, and manually build the parts of the body of the request. Not very easy, but feasible, and should work with IE6-9.

MaxArt
  • 20,295
  • 8
  • 70
  • 78
  • The second parameter for `Blob` should probably be `{ type: "image/png" }` – leopik Apr 22 '15 at 08:48
  • If I understand correctly, the file will arrive in $_POST, not in $_FILE. I'm looking for it to arrive in $_FILE so that we don't have to modify the server code. This method, however, appears better than our alternate strategy of base64 encoding and transmit via JSON. – Mark Kasson Apr 23 '15 at 00:13
  • @MarkKasson No, when a `File` or a `Blob` object is [appended](https://developer.mozilla.org/en-US/docs/Web/API/FormData/append) it will be sent as a file and treated as such by php. See also [this](https://developer.mozilla.org/en-US/docs/Web/Guide/Using_FormData_Objects). – MaxArt Apr 23 '15 at 05:38
1

I had a similar issue a while back one thing to note, I was not able to send the file to PHP via the $_FILE global, but we can do the exact same thing with the $_SERVER['HTTP_X_FILENAME']. I wrote the following JS function.

function UploadFile(file) {
    var xhr = new XMLHttpRequest();
    if (xhr.upload && file.size <= $id("MAX_FILE_SIZE").value)
    {
        // start upload
        xhr.open("POST", $id("upload").action, true);
        xhr.setRequestHeader("X-FILENAME", file.name);
        xhr.onload = function(e) {
            if (this.status == 200) {
                ... Some processing script for returning messages
            }
        };
        xhr.send(file);
    }
}

On the PHP side use the following to access the file:

$fn = (isset($_SERVER['HTTP_X_FILENAME']) ? $_SERVER['HTTP_X_FILENAME'] : false);
if ($fn) {
    $file = "desired location/" . $fn;
    file_put_contents($file,file_get_contents('php://input'));
}

You need to pass your JS variable into the UploadFile function and write a handler for the returning data.

Samuel Hawksby-Robinson
  • 2,177
  • 4
  • 20
  • 23
  • Disappointing to hear there's no way to get it to appear in $_FILE - that's exactly what we're hoping to accomplish. – Mark Kasson Apr 23 '15 at 00:13
0

To complete the answer of MaxArt

The code to receive the data in Php would be :

$file = $_POST['theFile'];//sent from javascript
$filePath = "/your_destination_directory/filename.ext";

if(file_put_contents($filePath,$file))
{
    //OK
}else{
    //ERROR
}
Vindic
  • 479
  • 4
  • 8
0

If you are using jQuery on client side, then jQuery Form Plugin is also a good option to upload files through Ajax and you will easily get the $_FILE through PHP. This plugin also has some extra functionality to display progress on file upload.

Here is the demo of the plugin: http://malsup.com/jquery/form/progress3.html

jogesh_pi
  • 9,477
  • 4
  • 31
  • 61
  • I could be wrong but it appears that is for uploading files that are stored on the disk. Ours are not - they are stored in memory in a variable and I don't want to store them in a file. – Mark Kasson Apr 23 '15 at 00:14