This is my first post to Stack Overflow so please forgive me if I have used incorrect formatting or conventions. I am trying to write a test scenario which receives a png image from a webpage POST (multipart/form-data), strips out the image which was posted and forwards that on to a 3rd party as Content-Type: image/png.
I have a php file (catcher.php) which is the recipient of the forwarded image. Post.php, the php file that posts the uploaded image to catcher.php is below:
<?php
$img = imagecreatefrompng($_FILES['myfile']['tmp_name']);
imagepng($img);
$opts = array(
'http'=>array(
'method'=>"POST",
'content'=>$img,
'header'=>"Content-Type: image/png\r\n"
)
);
$context = stream_context_create($opts);
file_get_contents( "http://localhost/catcher.php", false, $context);
?>
Post.php gets the file just fine from the webpage that posts it as multipart/form-data, however I am unsure how to access the image/png content in catcher.php.
My question is, in catcher.php, how do I access the image content? I have tried $_POST['content'] and I obtain the following error: "Undefined index: content". So I know I am just not looking for the correct data. Is there a specific superglobal variable such as $_POST or $_REQUEST that I can use to access the posted image content, or is there some other solution?
RESOLUTION
I was able to find the result I was looking for with the following code for catcher.php:
$input = fopen("php://input","+r");
$destination = fopen($target_path, 'w');
stream_copy_to_stream($input, $destination);
fclose($input);
fclose($destination);
?>
Thank you both Marc and Brenden for your expedient responses!
imagepng($img) does an immediate output of the binary garbage comprising the PNG. it's not captured into a variable. What you're actually posting is a string that probably says "GD Resource #7" or something similar.
The whole imagepng() bit is useless anyways - you're decoding a PNG into an in-memory representation, then trying to re-encode to PNG again. A pointless waste of memory, since the file is already on disk. You could do the whole thing with:
<?php
if ($_FILES['myfile']['error'] !== UPLOAD_ERR_OK) {
die("Upload failed with error code " . $_FILES['myfile']['error']);
}
$opts = array(
'http'=>array(
'method'=>"POST",
'content'=> file_get_contents($_FILES['myfile']['tmp_name']),
'header'=>"Content-Type: image/png\r\n"
)
);
$context = stream_context_create($opts);
file_get_contents( "http://localhost/catcher.php", false, $context);
Note the addition of checking for upload success - assumingn an upload succeeded will cause you grief down the line.
That being said, you're also not doing a proper POST file upload. For that to work, you have to actually simulate a full-blown HTML form with <input type="file"> present, and enctype="multipart/form-data" and whatnot. All you're doing is sending a raw PNG to the server.
You can probably retrieve it by reading from php://input in your catcher script.
The problem is that your data isn't encoded as multipart/form-data, it's just a PNG.
You have two options:
Encode the data correctly for a POST -- then you can read it from $_POST or $_REQUEST.
Keep post.php how it is and read the raw data from php://input in catcher.php.
For option 1, it looks like HttpRequest handles form encoding for you.
Related
I am trying to add attachments to a task using the php asana library (https://github.com/Asana/php-asana). I am successful in 'adding' the files, but when I open them in the task they are completely empty or corrupt.
I have tried .png, .doc, and .pdf all with the same result. My request looks like this:
$attachment = $client->attachments->createOnTask(
$task->id,
'screenshot_from_2016-07-08_140457.png',
'http://edit.local.org/sites/default/files/webform/change-request-materials/screenshot_from_2016-07-08_140457_8.png',
'image/png'
);
I have also tried using the relative path for the filename /sites/default/files/webform/change-request-materials/screenshot_from_2016-07-08_140457_8.png but get the same result.
This is the 'example code' I used from the library, seems pretty straightforward.
// add an attachment to the task
$demoAttachment = $client->attachments->createOnTask(
$demoTask->id,
"hello world",
"upload.txt",
"text/plain"
);
Also tried using 2 versions of the the curl request in https://asana.com/developers/api-reference/attachments just to see if I could get the attachments to work at all.
First one:
curl -H "Authorization: Bearer <personal_access_token>" https://app.asana.com/api/1.0/tasks/152938418205845/attachments --form "file=#http://edit.local.org/sites/default/files/webform/change-request-materials/screenshot_from_2016-07-08_140457_12.png;type=image/png"
Resulted in
curl: (26) couldn't open file "http://edit-fca.local.org/sites/default/files/webform/change-request-materials/screenshot_from_2016-07-08_140457_12.png"
And I've 777 on the file and the folder the file is in. So I decided to remove the '#' in front of the file and then got:
{"errors":[{"message":"file: File is not an object","help":"For more information on API status codes and how to handle them, read the docs on errors: https://asana.com/developers/documentation/getting-started/errors"}]}
which when I went to that URL didn't really tell me anything about the File not an object error.
A bit stuck as the php-asana library seems to at least put the files there, but they are empty. While the curl request just seems to not work at all.
Btw I'm using php 5.5.9.
I've tried out the example code in the php library and it seems to work fine. I think you may have misunderstood the arguments you are passing to createOnTask. Also, it seems you are passing it the path of a file on the internet you want to upload, but what you can actually do is pass the exact data you want to upload. I'm not familiar enough with php to show you how to get the contents of a file from the internet, but if you have a file locally you can use file_get_contents.
Let's examine the sample code and your code:
$demoAttachment = $client->attachments->createOnTask(
$demoTask->id,
"hello world", // Contents of file
"upload.txt", // The file name of the attachment
"text/plain" // encoding
);
vs
$attachment = $client->attachments->createOnTask(
$task->id,
'screenshot_from_2016-07-08_140457.png', // This should be your image data- but like encoded the right way
'http://edit.local.org/sites/default/files/webform/change-request-materials/screenshot_from_2016-07-08_140457_8.png', // this should be the filename from above
'image/png'
);
Heres an example of how you can do this with an image in the same folder.
$demoAttachment = $client->attachments->createOnTask(
$demoTask->id,
file_get_contents("someimage.png"), // Contents of file
"upload.png", // The file name of the attachment
"image/png" // encoding
);
For reference, see https://asana.com/developers/api-reference/attachments.
I got the docs from the third party that is sending me a file over http protocol and I need to write a script that will successfully receive the sent file. Content-type is set as application/gzip so I can't pick up the file uploaded using a $_FILES variable as it would be easy with multipart/form-data.
This link gave me a hint: http://php.net/manual/en/features.file-upload.post-method.php
Note:
Be sure your file upload form has attribute enctype="multipart/form-data" otherwise the file upload will not work.
I tried to reproduce their "client" side to test my server using the example in the following url http://blog.derakkilgo.com/2009/06/07/send-a-file-via-post-with-curl-and-php/
And to ensure crosdomain posting is available, I used a function posted and explained by #slashingweapon CORS with php headers
There must be a way to do it - Halp!
Hi what I understand is you just need to download the file that has been uploaded to a server, try getting the file in binary mode using the below code:
ftp_fget($conn_id, $file, FTP_BINARY, 0);
Ref: http://php.net/manual/en/function.ftp-get.php
The connection details must be shared with you by the 3rd party who is sharing the file.
Thanks to #fusion3k who pointed me to the right direction.
$rawData = file_get_contents("php://input") gave the the RAW data from which I had to parse the file from. It was painful to extract it because it was a binary file. I used
Explode the data with "\n" as a delimiter $rawData = explode("\n", $rawData)
Skip first few lines (it was 3 lines of header data for me) and take the rest into $valuableData
Convert the last line of data from string to binary using $convertedLine = unpack("H*", $valuableData[count($valuableData)-1])
Cut out the last byte of data from the last row $convertedLine[1] = substr($convertedLine[1], 0, -2) ( have no idea why is `unpack returning an array)
$valuableData[count($valuableData)-1] = pack("H*", $convertedLine[1])
implode("\n", $valuableData) and write that to a file
I am using file_put_contents($filename, $jpg) to upload my jpg files to some location.
How to use file_get_contents ($filename); with ($GLOBALS["HTTP_RAW_POST_DATA"])?
I am trying something like $jpg = $GLOBALS["HTTP_RAW_POST_DATA"];
$img = $_GET["img"];
$filename = "applicantsPhotos/applicantPhoto". mktime(). ".jpg";
file_put_contents($filename, $jpg);
echo file_get_contents ($filename); die;
but this is not working well(neigther I am getting filename, Not die stops script). Am I using wrong method to get the name ?
You should know what is exactly raw POST data:
$_POST can be said as and outcome after splitting the $HTTP_RAW_POST_DATA, PHP splits the raw post data and formats in the way we see it in the $_POST
For example if $HTTP_RAW_POST_DATA looks something like this:
key1=value1&key2=value2
then $_POST would look like this:
$_POST = array(
"key1" => "value1",
"key2" => "value2",);
Most probably you include some other things (elements) from the post in your *.jpg data. Make sure you include only raw and valid *.jpg picture information, not other elements.
Also keep in mind that $HTTP_RAW_POST_DATA is not available with form's type enctype="multipart/form-data".
To get the Raw Post Data use:
<?php $postdata = file_get_contents("php://input"); ?>
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input instead of $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives.
More information here, here and here.
The following problem I can't really wrap my mind around, so really if you guys can't be bothered to supply the entire code some tips leading in the right direction would be great!
So, I have a script where users can upload images to a server. PHP takes care of validating the file and saving it using a new filename in another folder, neither known by the client. Now, the client should be able to see the uploaded image, in html simply:
style="background-image:url('testimagegif.gif');
But preferably the client should not be able to see the path nor the file name of the image saved on the server. I know about using header('Content-type: ... for forcing the client browser to download files, but I do not see how this, nor any similar solution could be applied to this case. Same goes for readfile. If I use it the browser simply downloads the image, not placing it in the html.
You should probably be moving the files into a publicly readable folder on your webserver if you want to serve them.
Otherwise, you'll need something like readfile()
There are two options for this, you could use the data protocol, which would embed the whole image into the URL of the background ( this isn't recommended if the image is bigger than a few kb. ) or you can use a script to present the image by encoding or recording a unique key for the image, eg bg.php?id=4323-34442-3432-4532 which checks a db for the id to retrieve the file path then echoes the content with the right content type.
Some examples;
based on the Data URI wikipedia page
Data URI Method
Assuming a function like this;
function data_uri($fileID) {
$fRecord = mysql_fetch_array(
mysql_select("SELECT filePath, mimeType from fileTable WHERE fileID = " $fileID . ";")
);
$contents = file_get_contents($fRecord['filePath']);
$base64 = base64_encode($contents);
return "data:$fRecord['mimeType'];base64,$base64";
}
Then in your html/php page you'd have the following snippet
style="background-image:url('<?php echo data_uri($fileID);?>'
PHP Image Dump
Assuming a function like this;
// Given a filename and a mimetype; dump the contents to the screen
function showDocumentContent($fileID){
$fRecord = mysql_fetch_array(
mysql_select("SELECT filePath, mimeType from fileTable WHERE fileID = " $fileID . ";")
);
header( 'Content-Encoding: none', true );
header( 'Content-Type: ' . $fRecord['mimeType'], true );
echo readfile( $fRecord['filePath'] );
}
Then in your html page you'd have this;
style="background-image:url('image.php?fileID=123')
In the first case, images larger than a few KB will result in equally large HTML pages, and may not be supported in browsers consistently. In the second case, you'd effectively have created a php script that is pretending to be an image. In both cases, the real path to the binary files on your server is abstracted away by storing a mapping in a database.
If you store the paths to the files somewhere like a database or a file, you can use readfile() to output the file once you retrieve the path.
Combine that with the content-type header, and set the background-image URL to the PHP script with the correct query string like so:
style="background-image:url('script.php?img=30382');"
You must expose some path to the client, because their browser has to access the file. You can use your webserver config to serve at an indirected location, or serve the image with PHP and have the real path in a call to readfile()
I have a canvas and I want to upload the canvas context to the server using ajax and php. I want the final output to be an image stored on the server. I have done image uploading using form. But now I want to get the canvas context convert it to image and upload to the server!
So, how can i do that? Any suggestions, algos or solutions are appreciated!
This blog post aptly describes the method of saving canvases onto the server with AJAX queries, I guess this should be fitting for you.
Basically, you will need a var canvasData = testCanvas.toDataURL("image/png"); to retrieve the canvas' contents in JavaScript. This will be a Base64 encoded string, something like this: data:image/png;base64,fooooooooooobaaaaaaaaaaar==.
The following code will make sure the AJAX query sends the contents to the HTML:
var ajax = new XMLHttpRequest();
ajax.open("POST",'testSave.php',false);
ajax.setRequestHeader('Content-Type', 'application/upload');
ajax.send(canvasData);
On the server, in the PHP script, you will have a key named HTTP_RAW_POST_DATA in the $GLOBALS array, this will contain the data we just fetched.
// Remove the headers (data:,) part.
$filteredData=substr($GLOBALS['HTTP_RAW_POST_DATA'], strpos($GLOBALS['HTTP_RAW_POST_DATA'], ",")+1);
// Need to decode before saving since the data we received is already base64 encoded
$decodedData=base64_decode($filteredData);
$fp = fopen( 'test.png', 'wb' );
fwrite( $fp, $decodedData);
fclose( $fp );
Of course, test.png is the filename you will save. The first line is required to remove the data:image/png;base64, part of the encoded image, so that it can later be decoded by base64_decode(). It's output ($decodedData) will be saved to the file.