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.
Related
Rrecently I'm creating a telegram bot using telegram Bot API.
My plan is to place a single button in a page for uploading a specific folder's files, to telegram with cUrlFile uploading;
so far, I'm done my work with uploading but my purpose is large-sized files. To do this I need to show user some kind of progress bar that shows user how much MBs or KBs Uploaded.
My upload function is looks something like this:
function sendFile($token,$photosArray,$chatsArray){
$ch = curl_init('https://api.telegram.org/bot'.$token.'/sendDocument');
$cfile = new CURLFile(realpath($photosArray['path']),'image/jpg',$photosArray['name']);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION , false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
foreach($chatsArray as $chatId){
$data = array('chat_id' => $chatId, 'document' => $cfile);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$res=curl_exec($ch);
}
return $res;
}
For now its works but I don't have any idea how can I get uploaded size from this curl and show it to user. of course i mean real-time progress bar.
In other questions I found questions like :
cURL download progress in PHP
But it's not my answer.
Whats I'm looking for is to do this:
1- Click on a button to upload a folder files
2- Upload one file at a time and show a live progress bar to user
3- When upload is completed, start uploading next file and show another progress bar for it and so on.
Is it needs to implemented by AJAX or something else?
I'm pretty new in php so if someone can help me in a simple way I'll all ears.
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');
What i really want to do is:
User will upload to script from a html page
The script will login and return back the link
Well, all can be easily done with the help of curl and accepting file through multipart post.
But the problem here is that it will start uploading the file from server to another through curl after all upload is done :( So that will take a long process.
I was wondering whether its possible to make it like as user uploads files, it also keep sending the data in chunks like downloading a file
I am not sure whether this is even possible with php. If not, any other way through which this can be made possible
You can do this using cURL:
// Open a stream so that we stream the image download
$localFile = $_FILES[$fileKey]['tmp_name'];
$stream = fopen($localFile, 'r');
// Create a curl handle to upload to the file server
$ch = curl_init($fileServer);
// Send a PUT request
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
// Let curl know that we are sending an entity body
curl_setopt($ch, CURLOPT_UPLOAD, true);
// Let curl know that we are using a chunked transfer encoding
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Transfer-Encoding: chunked'));
// Use a callback to provide curl with data to transmit from the stream
curl_setopt($ch, CURLOPT_READFUNCTION, function($ch, $fd, $length) use ($stream) {
return fread($stream, $length) ? '';
});
curl_exec($ch);
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.
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);