How to save image server side when send from javascript - php

I'm was making a drag and drop upload script by reading a bunch of tutorials, but they only cover the javascript part, and i'm having issues on the php part.
I'm uploading a image as this:
$('#drop-zone').bind('drop', drop);
function drop(e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer = e.originalEvent.dataTransfer;
traverseFiles(e.dataTransfer.files);
}
traverseFiles makes a foreach loop for every file and calls upload funcion, there i do this:
xhr = new XMLHttpRequest();
//some event listners for processing, on load
xhr.open("post", "core/plugins/upload/upload.class.php", true);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.setRequestHeader("X-File-Size", file.size);
xhr.setRequestHeader("X-File-Type", file.type);
xhr.send(file);
then in php i found using this will get me raw data of the image
$file = file_get_contents('php://input');
EDIT: solution found
$fh = fopen($savedir, 'w') or die("can't open file");
fwrite($fh, $file);
fclose($fh);

Assuming you have managed to get the raw file from the PHP input, it's likely going to be base64 encoded. A simple example would be to do this:
<?php
//decode file
$image = base64_decode($file);
// write it
$filename = "myfile.png";
$fh = fopen($filename, 'w') or die("can't open file");
fwrite($fh, $image);
fclose($fh);
Edit
See comments, the file wasn't encoded as a result of the request.

move_uploaded_file is not what you want. If you had sent the file with a normal POST request (rather than through Ajax), that's when you'd use move_uploaded_file.
$file contains the raw binary data for the image. All you have to do is write that data into a file (taking note to properly handle linebreaks) and you're good to go. Start with fopen and see how far you get.
I'm assuming that $file has been successfully populated with the binary data and that you've tested this. If not, then you've got another problem on the javascript side.
Edit: you may also find this helpful.

Related

readfile('filename.exe') and decode base64?

I'm using php in order to stream a file as a download. A part of this uses readfile:
<?php
// headers etc...
// ...
readfile('file.exe');
?>
This is a binary file, but for various reasons (that are not relevant to this question) I need to store this file as base64 or similar.
How do I stream a file with readfile that is stored encoded with base64?
I guess there are many ways that lead to success here, but I'm looking for the best & most convenient.
Using stream filters should help:
$inFile = 'file.exe';
$outFile = 'php://output';
$inHandle = fopen($inFile, 'r');
$outHandle = fopen($outFile, 'w');
stream_filter_append($inHandle, 'convert.base64-decode');
stream_copy_to_stream($inHandle , $outHandle);
fclose($inHandle );
fclose($outHandle);
If the file is not too big you can read it using file_get_contents and then decode it with base64_decode:
<?php
$content = file_get_contents('file.exe');
echo base64_decode($content);

PHP input stream returning 0 data - Laravel

I'm trying to get chunked uploads working on a form in my Laravel 4 project. The client side bit works so far, the uploads are chunking in 2MB chunks, and data is being sent from the browser. There's even have a handy progress bar in place to show the upload progress.
The problem is on the PHP side, as I'm unable to write the contents of the upload stream to disk. The system always ends up with a 0 byte file created. The idea is to append the chunks to the already uploaded file as they arrive.
The project is built on Laravel 4, so I'm not sure if Laravel reads the php://input stream and does something with it. Since php://input can only be read once, it possibly means that by the time when my controller actually tries to read it the stream, it would be empty.
The controller looks as follows:
public function upload()
{
$filename = Config::get('tms.upload_path') . Input::file('file')->getClientOriginalName();
file_put_contents($filename, fopen('php://input', 'r'), FILE_APPEND);
}
The file is being created, but it's length always remains at 0 bytes. Any ideas how I can coax the contents of the php://input stream out of the system?
afaik fopen returns a pointer to file, and not an stream, so probably it is not good as a parameter for file_put_contents
can you try with this workaround, instead of your file_put_contents?
$putdata = fopen("php://input", "r");
$fp = fopen($filename, "a");
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
fclose($fp);
fclose($putdata);
The answer to this is simple, I needed to turn off multipart/form-data and use file_get_contents("php://input") to read the contents and pass the result to file_put_contents() like so:
file_put_contents($filename, file_get_contents("php://input"), FILE_APPEND);
This works and fixes my problems.

HTTP PUT Request: Passing Parameters with File

After numerous various tests with uploading files throught HTTP POST Request, it looks that HTTP PUT Requests are the most suitable for very large files +1GB upload.
The below listed simple code I have tested for HTTP PUT file upload request works well:
JavaScript:
var req = createRequest();
req.open("PUT", "PHP/filePutLoad.php");
req.setRequestHeader("Content-type", "text/plain");
req.onload = function (event)
{
console.log(event.target.responseText);
}
req.send(aUploadedFile.file_object);
PHP:
include 'ChromePhp.php';
require_once 'mysqlConnect.php';
ini_set('max_execution_time', 0);
ChromePHP::log( '$_PUT :' . print_r($_PUT));
/* PUT data comes in on the stdin stream */
$putdata = fopen("php://input", "r");
/* Open a file for writing */
$fp = fopen("myputfile.ext", "w");
/* Read the data 1 KB at a time and write to the file */
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
/* Close the streams */
fclose($fp);
fclose($putdata);
However, I have difficulties delivering arguments and variables with the file being uploaded from JavaScript to PHP. For example, I need to deliver upload target folder, where the new data needs to be stored, ID of the uploader, etc..
Is there a way to combine HTTP PUT Request with HTTP POST to submit arguments?
What are my options if I wish to deliver parameters from JavaScript to PHP along HTTP PUT file upload?
Thank you.
using PUT also, it works when you append the parameters in the query string. I'm also looking for another way for this. Although, this is a workaround I'm using currently
curl -X PUT "http://www.my-service.com/myservice?param1=val1" --data #file.txt

PHP , sharing a variable valuable across external javascript files

http://www.shedlimited.debrucellc.com
The site allows users to upload an image, via PHP script(ajaxupload.php) which is stored in $uploaded_img , inside of the php script. I want to pass the PATH of my newly stored image to a JS file, and the only way I've found to do it is by writing the value to a text file, which is extreme overkill
file_put_contents("testFile.txt", "");
$myFile = "testFile.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = $upload_image;
fwrite($fh, $stringData);
$stringData = "\n";
fwrite($fh, $stringData);
fclose($fh);
At the same time, I have an external .js file running which loads my html5 Canvas etc,
I set a global variable sourcer , inside the external .js file, which I'm able to access and update from my index.php by reading the URL from the file which I wrote the url to in my php script.:
jQuery.get('scripts/testFile.txt', function(data) {
sourcer = data;
});
Is there any way that I can pass the URL value to sourcer without having to manually insert it in a text file?
Add a block to your head on your php template.
<script type="text/javascript">
var uploaded_img = '<?php echo json_encode($uploaded_img); ?>';
</script>
The json encode makes sure the variable is properly encoded, even if it is an object or array.
If it is purely an ajax thing. Just return the filename in your ajax response.
So post to your ajax upload, and make your ajax script return a json object with the filename.
So in your upload script, at he bottom:
header('Content-type: application/json');
echo json_encode(array('filename'=>$uploaded_img));
And read the response.filename in javascript.
What about using a session variable to store the uploaded image AND an ajax response to work with ?
I see an advantage to use both : you can use the value directly on the upload page right after the image is uploaded. And for the session var, it will ensure that the server side is always able to get the value if you ever need to access it from another context.

Uploading large files with PUT method

I have a page with html5 drag and drop upload feature and the file is uploading using PUT method. If I upload large image files, only part of the image is getting saved into the server. Im using the following PHP code to save the file
$putdata = fopen("php://input", "r");
$fp = fopen("/tmp/myputfile" . microtime() . ".jpg", "w");
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
fclose($fp);
fclose($putdata);
Anything wrong with this ? please help
I think is becos the entire file is not completely uploaded yet when you try to read, so it sometimes will return you zero bytes read. But there might still be data being uploaded.
Maybe you can try using the feof function to check if there is any more data to be read?
see "http://www.php.net/manual/en/function.feof.php"
If you are on Windows, you should add the "b" to the mode-parameter of fopen(). see manual BTW. it is only a good idea to add the param for code-portability...

Categories