Here is my problem. I have a ticket-tracking system that is not very 'user friendly' but I have a desire for my users to submit 'tickets' to the system without having them to see it.
I got as far as just using a custom HTTP Form and posting to the ticket tracking system. One problem is the 'success/completion' page has a tendency to confuse people. So I figured... well since I cant change the ticket system to use a different 'success' page. I will just handle the HTTP Post exchange with CURL and report a custom success or problem page. Heres some abstracted code.
File: tickethelper.php
<?php
extract($_POST);
$url = 'TICKETSYSTEMURL';
$fields = array(
'fullname'=>urlencode($fullname),
/*many more fields*/
);
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string,'&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
curl_setopt($ch, CURLOPT_MAXREDIRS, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec($ch);
curl_close($ch);
if((strlen(strstr($contents,'Your ticket has been submitted')))>0){
header("Location: http://THANKYOU");
}
else{
header("Location: http://OOPS");
}
?>
However, what I realized is that I am missing my file upload. Most of the CURL examples I have seen are to do with uploading local files to a remote HTTP POST page.
How do I handle receiving a file from my users HTTP form, process this in the 'tickethelper' and POST that to the 'TICKETSYSTEMURL' ?
-Israel
Well, I can't say I've done this myself, but according to the PHP documentation regarding CURL and File Handling (PHP.net)
CURLOPT_INFILE | The file that the transfer should be read from when uploading.
value should be a stream resource (using fopen(), for example) for the following values of the option parameter:
You should be able to call fopen() on the file that has been uploaded (refer to documentation regarding Handling File Uploads) I'm not sure, but you may need to call move_uploaded_file() to a controlled directory on the server before calling fopen()
For example:
$ch = curl_init();
$file = fopen($_FILES['file-field-name']['tmp_name'], 'r');
// OTHER CURL CONFIGURATION
curl_setopt($ch, CURLOPT_INFILE, $file);
curl_exec($ch);
First, your script can access the uploaded file through the $_FILES array.
From http://www.tizag.com/phpT/fileupload.php
The $_FILES array is where PHP stores
all the information about files. There
are two elements of this array that we
will need to understand for this
example.
uploadedfile - uploadedfile is the reference we assigned in our HTML
form. We will need this to tell the
$_FILES array which file we want to
play around with.
$_FILES['uploadedfile']['name'] - name contains the original path of the user uploaded file.
$_FILES['uploadedfile']['tmp_name'] -
tmp_name contains the path to the
temporary file that resides on the
server. The file should exist on the
server in a temporary directory with a
temporary name.
To include this file in the POST you send with libcurl, use an array of fields instead of a string. Include the file as one of the fields:
$post_fields = array (
$key => $value,
...
$file_key => "#" . $filename,
);
If you use the "#" symbol, libcurl will read the file and include it in the POST.
Then use
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
Related
I am using CURL to POST upload files on a web-service. Server returns a XML with file name with which it puts file in a storage DB for further processing. Simplified code below:
$post['uploadfile'] = new CurlFile('src/files/file.png', 'image/png');
$ch = curl_init($target_url);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch);
Server side code is unavailable for me, and the problem is that server returns me a path for the uploaded file like this:
src_files_file.png
I guess i have missed a field in request, that holds clear name for file. How could it be resolved to
file.png
I not sure that I fully understand your question, but I think you search third parameter in CurlFile constructor:
$post['uploadfile'] = new CurlFile('src/files/file.png', 'image/png', 'file.png');
I am fetching data from API of a service provider (Say- http://serviceprovider.com).
From several parameter one is MP3 download Link (example- http://serviceprovider.com/storage/read?uid=475b68f2-a31b-40f8-8dfc-5af791a4d5fa_1_r.mp3&ip=255.255.255.255&dir=recording)
When I put this download link on my browser it saves it to my local PC.
Now My Problem -
I want to save this MP3 file in one of folder on my hosting space, from where I can further use it for playing using JPlayer Audio.
I have tried file_get_contents(), but nothing happened.
Thanks in advance.
Edit:
After reading Ali Answer I tried the following code, But still not working fully.
// Open a file, to which contents should be written to.
$fp = fopen("downloadk.mp3", "w");
$url = 'http://serviceprovider.com/storage/read?uid=475b68f2-a31b-40f8-8dfc-5af791a4d5fa_1_r.mp3&ip=255.255.255.255&dir=recording';
$handle = curl_init($url);
// Tell cURL to write contents to the file.
curl_setopt($handle, CURLOPT_FILE, $fp);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_HEADER, false);
// Do the request.
$data = curl_exec($handle);
// Clean up.
curl_close($handle);
fwrite($fp, $data);
fclose($fp);
This created the file download.mp3 file on my server but with 0 bytes, i.e. empty.
The url used here is a download link example not a mp3 file that can be played with modern browser directly.
Function file_get_contents is used for reading local files. What you have is an URL and in order to fetch the contents, you need to do a HTTP request in your script. PHP comes with the curl extension, which provides you with a stable library of functions for doing HTTP requests:
http://php.net/manual/en/book.curl.php
Using curl to download your file could be done like this:
// Open a file, to which contents should be written to.
$downloadFile = fopen("download.mp3", "w");
$url = "http://serviceprovider.com/storage/read?uid=475b68f2-a31b-40f8-8dfc-5af791a4d5fa_1_r.mp3&ip=255.255.255.255&dir=recording";
$handle = curl_init($url);
// Tell cURL to write contents to the file.
curl_setopt($handle, CURLOPT_FILE, $downloadFile);
// Follow redirects.
curl_setopt($handle, CURLOPT_FOLLOWLOCATION, true);
// Do the request.
curl_exec($handle);
// Clean up.
curl_close($handle);
fclose($downloadFile);
You should probably add some error checking.
I currently have a site which allows file uploads. When the user submits the form, I run a php script that sends off a curl request to my api.
Currently the php request looks like this:
$params = array(
'media' => "#" . $_FILES['media']['tmp_name']
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
And the api just checks the $_FILES field and then grabs media and runs move_uploaded_file.
So the file goes straight from user submitted form to curl to api server, with the file never being actually uploaded (besides being placed in a tmp folder between form submit and curl request) until it hits the api server.
This all works fine for uploading the file to the api server, but the problem is that the server thinks the file's extension is .tmp, as opposed to something like a png, because that's the file the curl request is sending.
How can I send the file without first uploading it pre-curl so that the api server knows what file is actually being sent?
Two ways:
Rename the tmp file. It is accessible to you, so renaming it is trivial: rename(oldname, newname)
Send a mimetype. The format is: #filename;type=image/png for a png.
Prefer the first option if you care about the filename, option two if you only care about the mime type.
I'm trying to download users profile picture from facebook in PHP using this function
public static function downloadFile($url, $options = array())
{
if (!is_array($options))
$options = array();
$options = array_merge(array(
'connectionTimeout' => 5, // seconds
'timeout' => 10, // seconds
'sslVerifyPeer' => false,
'followLocation' => true, // if true, limit recursive redirection by
'maxRedirs' => 2, // setting value for "maxRedirs"
), $options);
// create a temporary file (we are assuming that we can write to the system's temporary directory)
$tempFileName = tempnam(sys_get_temp_dir(), '');
$fh = fopen($tempFileName, 'w');
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_FILE, $fh);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $options['connectionTimeout']);
curl_setopt($curl, CURLOPT_TIMEOUT, $options['timeout']);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $options['sslVerifyPeer']);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, $options['followLocation']);
curl_setopt($curl, CURLOPT_MAXREDIRS, $options['maxRedirs']);
curl_exec($curl);
curl_close($curl);
fclose($fh);
return $tempFileName;
}
The problem is it saves the file in the /tmp directory with a random name and without the extension. How can I get the original name of the file (I'm more interested in the original extension)
The important things here are:
The url actually redirects to image so i cant get it from original url
the final url does not have the file name in headers
If the URL redirects to an image, you should still be able to get the filename from the headers. Using a browser with dev tools like Chrome, you can look at the headers going back and forth from your original request to the resultant file, and the filename has to be in there somewhere. With that said, I was under the impression that Facebook rewrites all images to their own filenames for privacy reasons.
You can recreate the extension based on the content type of the response.
After running curl_exec(), try:
$content_type = curl_getinfo($curl,CURLINFO_CONTENT_TYPE);
This will return something like "image/jpg" for a JPEG, for example. You can then rename your temp file to have the proper extension.
If you can use PHP 5.3, a possibly cleaner way to do this would just be to call finfo_file() on the file after it is downloaded, which should read the MIME type, allowing you to select a proper extension without relying on header data. finfo_file() is also available in the fileinfo PECL extension.
If you're just looking for the image type (jpg/png/gif) and you have the GD extension installed you can use getimagesize, it returns the image type along with other details. It's more accurate than looking at the file extension.
image_type_to_mime_type might also help once you've used getimagesize.
I have been researching this for a while and have not been find an answer for this.
I have a Client Site making calls to our API Server. What I would like to transfer an image to the Client Site when a special call is made.
I have some code that downloads the image from the server, but this is causing us to make multiple calls forcing us to create all these images in the server that we don't want to keep, even if we delete them afterward.
$originalFileUrl = createImage('createImage', $fileName);
downloadImage($originalFileUrl, $fileDestination);
deleteFileFromServer('deleteImage', $fileName);
function serverCall ($action, $fileName) {
$serverCall = $SERVER.'/api.php?fileName=' . $fileName . '&action=' . $action;
ob_start();
$ch = curl_init();
$timeout = 5;
curl_setopt ($ch, CURLOPT_URL, $serverCall);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_exec($ch);
$fileContents = ob_get_contents();
curl_close($ch);
ob_end_clean();
return $fileContents;
}
function downloadImage ($originalFileUrl, $fileDestination) {
// Starting output buffering
ob_start();
// create a new CURL resource
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $originalFileUrl);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// set timeouts
set_time_limit(30); // set time in secods for PHP
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // and also for CURL
// open a stream for writing
$outFile = fopen($fileDestination, 'wb');
curl_setopt($ch, CURLOPT_FILE, $outFile);
// grab file from URL
curl_exec($ch);
fclose($outFile);
// close CURL resource, and free up system resources
curl_close($ch);
ob_end_clean();
}
Where $originalFileUrl is the current location of the file, and $fileDestination is the path to where I want my new file to be.
My question is: Can I make a call to a PHP file in the Server that will be in charge of create, transfer and delete the image all in one call rather than doing multiple calls?
Also for multiple reasons ftp the file from the server to the client is not a good option.
Thank you
This will not be a trivial task. However, you should be able to design a successful approach. This won't be the most error-safe method of accomplishing the task, though. You're thinking right now of a HTTP-esque stateless protocol, which is manageable. If the description below doesn't sound good enough, consider another protocol which can maintain a constant bi-directional connection (like an SSH tunnel).
You'd likely suffer data overhead, but that would generally be more than acceptable in order to save multiple calls. To that end, I'd advise creating an XML interface. On the receiving end, your XML would have an element with either a Base64 representation of the image, or possibly a gzipped CDATA implementation. You don't have to stick to any XML standard, but if you do, the PHP XML Parser could help with some of the legwork.
So, to recap, in this model, the server end could receive a set of commands which do what you've called out: move the file into a processing folder, create a Base64 string of the file contents, craft the XMl package, and return it. The client will send a request, and process the response. If the client detects an error, it could retry and the server can still grab the file data from the processing queue.
If error becomes an issue and an open socket isn't a good option (because the coding is difficult), you could also develop a delete-batching system, where you track the files in the processing folder and only delete them on request. But, you'd only make delete requests from the client every once in a while, and possibly not as a part of any particular page with a user experience, but from a cron.