I query an API to which I upload files but no files are uploaded when I post using PHP7.4, however, it works fine with PHP7.3.
Here's a snippet of my code:
public function upload($opts = array())
{
$files = array();
foreach($opts['files'] as $i => $file)
{
$files['files[' . $i . ']'] = new CURLFile($file);
}
unset($opts['files']);
$data = array_merge($files, array( "data" => json_encode($opts)));
$response = self::curlRequest( "https://api.example.com/", $data);
return $response;
}
public static function curlRequest($url, $data)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_FAILONERROR, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
curl_setopt($curl, CURLOPT_TIMEOUT, 300);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 300);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
So the upload function accepts a multidimensional array of values including an array of files with index 'files'. It iterates through the files, creating CURLFile objects then posts these along with the rest of the data to the API.
Using PHP7.4, the global variables $_REQUEST and $_FILES on the API server are always empty. With PHP7.3 these variables are populated with the sent data as expected.
On https://www.php.net/manual/en/migration74.new-features.php it states:
CURLFile now supports stream wrappers in addition to plain file names, if the extension has been built against libcurl >= 7.56.0.
Libcurl version is 7.58.
A related bug report has been submitted here https://bugs.php.net/bug.php?id=79013 regarding the Content-Length header missing resulting in no file uploads but it seems the PHP team thinks the problem is with the server, not PHP.
Does anyone has any idea how to upload files using PHP7.4?
Version PHP 7.4.4 fixed this issue. Seems it was indeed a bug.
Related
I'm recently started developing on moodle and one big problem is that whenever i build a plugin with a web page, it don't execute any of my curl commands, i hear that moodle has his own php library(an php file called filelib.php i suppose) with curl commands and i should be using its commands instead of mine, but i don't have much experience with moodle development and php so all that code make me very confused.
i tried this question before and a gentleman helped me with an example, i tried his code and it didn't work(it changed the output but still show an error message, i also tried changing the code to no avail) and i didn't get much of an explanation about how curl commands work on moodle(i'm still grateful for his help) or whats commands on filelib.php will substitue my code, can someone help me?
my code:
<?php
require_once(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/filelib.php');
$PAGE->set_url(new moodle_url(url:'/local/iesde/selecionaraulas.php'));
$PAGE->set_context(\context_system::instance());
$PAGE->set_title('selecionar aulas');
$PAGE->requires->js_call_amd('local_iesde/tabelas', 'init');
echo $OUTPUT->header();
echo $OUTPUT->render_from_template('local_iesde/manageaulas', $templatecontext);
$api_server = 'url';
$api_http_user = 'user';
$api_http_pass = 'pass';
$key_acess = 'key';
$key_name = 'API-KEY';
$format = 'json';
$params = array(
'IDstudent' => 000000,
'IDcourse' => 000000,
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "{$api_server}/format/{$format}");
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_setopt($curl, CURLOPT_USERPWD, "{$api_http_user}:{$api_http_pass}");
curl_setopt($curl, CURLOPT_HTTPHEADER, array("{$key_name}:{$key_acess}"));
curl_setopt($curl, CURLOPT_NOBODY, 1);
curl_exec($curl);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
$output = curl_exec($curl);
var_dump(json_decode($output));
echo $output;
echo $OUTPUT->footer()
the purpose of this curl request is to print a list of ids that will be used on another curl request to generate a video file that will be executed on a videoplayer, the variables:
$api_server = 'url';
$api_http_user = 'user';
$api_http_pass = 'pass';
$key_acess = 'key';
$key_name = 'API-KEY';
$format = 'json';
$params = array(
'IDstudent' => 000000,
'IDcourse' => 000000,
);
Are all needed to execute the commands (one of the reasons i think the gentleman's example didn't work is that it didn't used all the variables of the code to get full validation).
well that is all, i'm very new to all of this so any explanation will help, thanks for the help.
I have a persistent volume defined in server under www/public/images/logo/
I want to list all the files inside that folder. So far I have done following lines with no luck.
public function getFiles($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$url = 'https://myurl.de/images/logo/';
$data = $this->getFiles($url);
Can anybody please help ?
If you are want to list all files on same server then you can use php function scandir();
If you are want to list all files on remote server then you need to connect it using ftp like below code.
$connection = ftp_connect("HOST_NAME");
$login = ftp_login($connection, "FTP_USERNAME","FTP_PASSWORD");
ftp_pasv($connection, true);
$fileList = ftp_nlist($connection,'DIRECTORY_ON_FTP');
ftp_close($connection);
Hello and thanks in advance, now I'm trying to upload a image to a prestashop 1.7 via webservice and I'm unable to insert a image in a product. I don't know what fails, because I don't get any response of the webservice, even with the debug enabled (I get the xml responses of the rest of the files, but not the ones from curl).
The variable $idProduct is a value passed to the function and is defined.
My code is the following:
$url = PS_SHOP_PATH."api/images/products/".$idProduct;
$dir_path_to_save = 'img/import/';
$img_path = getFile($remoteImageURL, $dir_path_to_save);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_USERPWD, PS_WS_AUTH_KEY.':');
curl_setopt($ch, CURLOPT_POSTFIELDS, array('image' => '#'.$img_path));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
echo print_r($response);
curl_close($ch);
The getFile function downloads the image to the server where is installed the prestashop and returns the path (returns a string with the real path where the image is stored, already tested).
I tried to make a form to upload the image (just for testing), but it returns "code 66 - unable to save this image". I don't know if this helps.
Thanks
UPDATE
A fellow programmer told me to use curl_file_create()
So I changed the $img_path declaration this way:
$img = curl_file_create($dir_path_to_save.'/'.basename($img_path));
Now everything works as intended.
I try to upload my database to bitbucket downloads section of my repository via a PHP script using curl library. Normally i go to my phpmyadmin and export my database to a folder, then going to my bitbucket account under downloads section of my repository and upload manually. I need a script that automates these tasks.
I tried using curl library like this:
// bitbucket username and password
define('USERNAME', 'my_username');
define('PASSWORD', 'my_password');
$url = 'https://bbuseruploads.s3.amazonaws.com/';
//This needs to be the full path to the file you want to send.
$file_name_with_full_path = realpath('apache_pb2.gif');
$post = array('extra_info' => '123456', 'file_contents' => '#' . $file_name_with_full_path); // image file example here
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, USERNAME . ":" . PASSWORD);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$resp = curl_exec($ch);
// validate CURL status
if (curl_errno($ch))
throw new Exception(curl_error($ch), 500);
The result:
<error><code>InvalidArgument</code>
<message>Unsupported Authorization Type</message>
<argumentvalue>Basic hash_code_here</argumentvalue>
<argumentname>Authorization</argumentname>
<requestid>hash_code_here</requestid>
<hostid>hash_code_here</hostid>
</error>
If you need further clarifications please let me know.
Just for the case someone finds this old corpse here:
I solved it by this funktion function:
/**
* Uploads a file to Bitbucket Download area of the configured repository
* Does the same as thi bash command:
* curl -X POST "https://USER:PW#api.bitbucket.org/2.0/repositories/owner/slug/downloads/" --form files=#"test.txt"
* #param string $filename
* #param string $apiEndpoint
* #param string $apiUser
* #param string $apiPassword
* #return bool|string
* #throws Deployer\Exception\Exception
*/
public static function sendFileToDownload(
string $filename,
string $apiEndpoint,
string $apiUser,
string $apiPassword
) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $apiEndpoint);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLAUTH_BASIC, 1);
curl_setopt($curl, CURLOPT_USERPWD, "$apiUser:$apiPassword");
$data = [
'files' => curl_file_create($filename),
];
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$erg = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($erg === false || $status > 300) {
throw new Deployer\Exception\Exception("Result: ".print_r($erg, true), $status);
}
curl_close($curl);
}
}
For me the most important point was this section:
$data = [
'files' => curl_file_create($filename),
];
This results in a local file been uploaded to my repos download area with the name $filename (filename path).
Had this same problem today. "Unsupported Authorization Type" response from an API CURL request.
I spent a long time consulting with Google. In the end, I discovered that my URL had two slashes in it together (accidentally). See, the API I'm connecting to has a URL, and then an API endpoint. Like this:
https://www.example.com/api/v2/foo -or-
https://www.example.com/api/v2/bar
But I accidentally was combining them like this:
curl_setopt($curl, CURLOPT_URL, $url ."/". $endpoint);
given my data:
$url = "https://www.example.com/api/v2/"
$endpoint = "foo"
I ended up with this:
"https://www.example.com/api/v2//foo"
Problem solved by removing the ."/". and just making it this: .
BONUS POSSIBILITY: Something else interesting I learned in the process was that the API folks prefer double-quotes around json data posted to them. I haven't verified it makes a difference, but instead of wrapping double-quotes in single-quotes (or visa-versa), escaping the internal double-quotes is how I left things. And it's working.
I have been working with Jira API and have seen inconsistent results for my requests. Sometimes it works and sometimes it doesn't. Last week I was able to post attachments to issues just fine, but now an old problem occurred: the names of the attachments contain the whole path of the posted file, hence the attachments can't be opened. I use json representation to post files:
$array = array("file"=>"#filename");
json_encode($array);
...
This gets the file posted but the problem is when it's posted the file names in JIRA are like this:
/var/www/user/text.text
Needless to say it can't be opened in JIRA. I had this problem before, then it suddenly disappeared, now it occurred again. I don't really get it. By the way I am not using curl for this request even though it might be recommended in the documentation.
I realize this question is somewhat old but I had a similar problem. It seems Jira doesn't necessarily trim the filename as expected. I was able to fix it with the following. If you're using PHP >= 5.5.0:
$url = "http://example.com/jira/rest/api/2/issue/123456/attachments";
$headers = array("X-Atlassian-Token: nocheck");
$attachmentPath = "/full/path/to/file";
$filename = array_pop(explode('/', $attachmentPath));
$cfile = new CURLFile($attachmentPath);
$cfile->setPostFilename($filename);
$data = array('file'=>$cfile);
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch);
$ch_error = curl_error($ch);
if ($ch_error){
echo "cURL Error: $ch_error"; exit();
} else {
print_r($result);
}
For PHP <5.5.0 but > 5.2.10 (see this bug):
$data = array('file'=>"#{$attachmentPath};filename={$filename}");
Yes, I filed an issue on this at https://jira.atlassian.com/browse/JRA-30765
Adding attachments to JIRA by REST is sadly not as useful as it could be.
Interesting that the problem went away - perhaps you were running your script from a different location?