HTTP PUT Request: Passing Parameters with File - php

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

Related

HTTP PUT to unique filename in PHP

I would like to use HTTP to transfer a file to a webserver and save it with a meaningful filename. I currently have the transfer part working, I need to make the meaningful filename piece work.
If I use Curl to transfer the file, I specify which file to send:
curl -X PUT http://user:passwd#x.x.46.9/put.php --data-binary "session"
The PHP script on the webserver is as follows:
/* 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);
?>
Is there a way to extract the filename sent in the HTTP PUT message and use this for the filename? Or, at the very least, is there a way to save the file using the IP address of the source device?
Much obliged.
Yes, you have all that information in the $_REQUEST variable.

Saving large files sent from .Net in PHP through PUT or POST method

I am having trouble in saving a large file ~200MB and above sent through desktop application made in .Net framework and receiving the file in PHP. The desktop application sending the file through writeStream function of .Net.
Problems:
1) I am getting the data in PHP but the final file size exceeds the original file size. For example if the file size is of 36MB the file PHP saves will be of 55MB.
2) And the file also get corrupted after saved on server.
Requirements:
1) I need to save a large file sent from .Net to PHP with any method that is working.
2) Any working example of the problem will be highly appreciated.
Note:
I am making a Dropbox like application. I hope this will give you a general idea of what kind of application I need to make.
PHP Code
/* PUT data comes in on the stdin stream */
$putdata = fopen("php://input", "r");
/* Open a file for writing */
$fp = fopen($targetDir.$fileName, "a");
/* 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);

HTTP PUT Request - Progress Bar Implementation

I have discovered that HTTP PUT Request ist the most suitable for very large files upload (1GB or more).
The solution works well and I can upload any file of my choice to the server. However, I have difficulties monitoring upload progress.
I have implemented onprogress callback, but this one gets called only once after the file is uploaded via PUT.
My JavaScript Code:
var req = createRequest();
req.open("PUT", "PHP/upload_file.php?folder=" + aUploadedFile.upload_folder + "&master_folder=" + settings.strServerSideMasterFolder + "&file_name=" + aUploadedFile.file_name);
req.setRequestHeader("Content-type", "text/plain");
req.onload = function (event)
{
console.log("OnLoad Called: " + aUploadedFile.file_name);
}
req.onprogress = function (event)
{
console.log("OnProgress Called: " + aUploadedFile.file_name);
}
req.send(aUploadedFile.file_object);
What are my options when i wish to monitor the upload progress via PUT, please?
Should I establish another JavaScript AJAX call, that will monitor the size of the uploaded file o the server?
Is there any other working solution available?
I use:
HTML5
JavaScript
PHP
Apache
I do not use:
jQuery
Thank you in advance.
Have you tried xhr.upload.onprogress instead of xhr.onprogress?
If that doesn't work too, you could establish another JavaScript AJAX call, like you said. Recently, I've made an upload system that read the file line per line, and it needed to show some extra information about the upload, and not just the percentage, so I did something like this:
The main page makes an AJAX request to a file responsible to process the file
In that file, I had to close the connection, so the AJAX request could complete, but the PHP script would still be running, using this:
ob_start();
$file = tempnam('/tmp', uniqid()); // create a temp file to show status of the action
echo json_encode(array('file' => $file));
header('Content-length: '.ob_get_length());
header('Connection: close');
ob_end_flush();
flush(); // The AJAX request is completed here, but the script is still running...
function writeToFile($handle, $arr) {
ftruncate($handle, 0); // empty file
fwrite($handle, json_encode($arr));
}
$handle = fopen($file, 'w');
while (readLine($uploadedFile)) {
// code to process line
writeToFile($handle, array('progress' => $current / $total, 'action' => 'Reading...'));
}
// insert into database
writeToFile($handle, array('progress' => '100', 'action' => 'Inserting into database...'));
fclose($handle);
At the main page, the AJAX request would return the name of the file that contains the information, so I would create several GET requests to that file, using setInterval method
Note: in my case, I created another PHP file to show the contents of the progress file (with file_get_contents), so I could manually delete that file when the operation completes

How to save image server side when send from javascript

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.

Offer a generated file for download from jQuery post

I've got a large form where the user is allowed to input many different fields, and when they're done I need to send the contents of the form to the server, process it, and then spit out a .txt file containing the results of the processing for them to download. Now, I'm all set except for the download part. Setting the headers on the response to the jQuery .post() doesn't seem to work. Is there any other way than doing some sort of iframe trick to make this work (a la JavaScript/jQuery to download file via POST with JSON data)?
Again, I'm sending data to the server, processing it, and then would like to just echo out the result with headers to prompt a download dialog. I don't want to write the result to disk, offer that for download, and then delete the file from the server.
Don't use AJAX. There is no cross-browser way to force the browser to show a save-as dialog in JavaScript for some arbitrary blob of data received from the server via AJAX. If you want the browser to interpret the results of a HTTP POST request (in this case, offering a download dialog) then don't issue the request via AJAX.
If you need to perform some kind of validation via AJAX, you'll have to do a two step process where your validation occurs via AJAX, and then the download is started by redirecting the browser to the URL where the .txt file can be found.
Found this thread while struggling with similar issue. Here's the workaround I ended up using:
$.post('genFile.php', {data : data}, function(url) {
$("body").append("<iframe src='download.php?url="+url+"' style='display: none;'></iframe>");
});
genFile.php creates the file in staging location using a randomly generated string for filename.
download.php reads the generated file, sets the MIME type and disposition (allowing to prompt using a predefined name instead of the random string in the actual filename), returns the file content and cleans up by deleting the source file.
[edit] might as well share the PHP code...
download.php:
<?php
$fname = "/tmp/".$_GET['url'];
header('Content-Type: text/xml');
header('Content-Disposition: attachment; filename="plan.xml"');
echo file_get_contents($fname);
unlink ($fname);
?>
genFile.php:
<?php
$length = 12;
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = substr( str_shuffle( $chars ), 0, $length ).'.xml';
$fh = fopen(('tmp/'.$str), 'w') or die("can't open file");
fwrite($fh,$_POST["data"]);
fclose($fh);
echo $str;
?>
Rather than using jQuery's .post(), you should just do a normal POST by submitting the form, and have the server respond with appropriate Content-Encoding and MIME-type headers. You can't trigger a download through post() because jQuery encapsulates the returned data.
One thing I see in use rather frequently, though, is this:
$.post('generateFile.php', function(data) {
// generateFile builds data and stores it in a
// temporary location on the server, and returns
// the URL to the requester.
// For example, http://mysite.com/getFile.php?id=12345
// Open a new window to the returned URL which
// should prompt a download, assuming the server
// is sending the correct headers:
window.open(data);
});

Categories