how to get image from url in php? - php

I have one remote url which outputs the image
The url is in format like this
http://domain.com/my_file/view/<file_id>/FULL/
In the url "my_file" is a controller name, "view" is a function name and the other two are the parameters
If I hit this url in browser it shows me image
I want to take that image in my projects folder
I have tried with file_get_contents but it gives me warning with 404
How can I achieve that?

$img=file_get_contents('http://example.com/image/test.jpg');
file_put_contents('/your/project/folder/imgname.jpg',$img);
This works only if allow_url_fopen is set to 1 in your php.ini file.
If you can change this value, enable it and you're done.
Another option is CURL. Check if this module is enabled in your PHP configuration.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://example.com/image/test.jpg');
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HEADER , 0);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$result = #curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);
if (empty($curl_err)) {
file_put_contents('/your/project/folder/imgname.jpg',$result);
}
If CURL is not enabled, your chance is to write a simple HTTP client like this:
$buf='';
$fp = fsockopen('example.com',80);
fputs($fp, "GET /image/test.jpg HTTP/1.1\n" );
fputs($fp, "Host: example.com\n" );
fputs($fp, "Connection: close\n\n" );
while (!feof($fp)) {
$buf .= fgets($fp,128);
}
fclose($fp);
file_put_contents('/your/project/folder/imgname.jpg',$buf);

Use Curl for this:
function curlFile($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
function readurl()
{
$url="http://domain.com/my_file/view/<file_id>/FULL/";
curlFile($url);
}
echo readurl();

If you are trying
$image = file_get_contents('http://domain.com/my_file/view/<file_id>/FULL/');
if($image) file_put_contents('some/folder/<file_id>');
and it does not work, it probably means either:
That there is access control that prevents it on the remote server. In that case, you must set the appropriate cookies. I suggest using curl to do that.
The image path is wrong; try to view source when navigating to http://domain.com/my_file/view/<file_id>/FULL/ using your browser.
The trailing / in your URL should not be there, e.g. http://domain.com/my_file/view/<file_id>/FULL?

Related

Get file in PHP which is generated when visiting URL

In PHP, how do I get a file that is generated when you visit a URL. To explain this, if you visit this Google Drive URL:
https://docs.google.com/document/d/1ZUqkdVQZqpHhE25m-5wxhN1uzK7EvoZ81bmrwiwk3CY/export?format=doc
Download will start. How do I grab that download file in PHP?
Though in theory file_get_contents should have worked for this situation it did not for me. I'm behind proxy.
To get more control I had to use curl
I left proxy configuration as a part of code but commented it out.
<?php
$url = "https://docs.google.com/document/d/1ZUqkdVQZqpHhE25m-5wxhN1uzK7EvoZ81bmrwiwk3CY/export?format=doc";
$fileToSave = dirname(__FILE__) . '/localfile.doc';
// $proxy = "127.0.0.1:8080";
set_time_limit(0);
//This is the file where we save the information
$fp = fopen ($fileToSave, 'w+');
//Here is the file we are downloading.
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
// write curl response to file
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
// Proxy stuff if you need it
// curl_setopt($ch, CURLOPT_PROXY, $proxy);
// ssl config here
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
// get curl response
if(curl_exec($ch) === false) {
echo 'Curl error: ' . curl_error($ch);
} else {
echo 'Done';
}
curl_close($ch);
fclose($fp);
$data=file_get_contents("https://docs.google.com/document/d/1ZUqkdVQZqpHhE25m-5wxhN1uzK7EvoZ81bmrwiwk3CY/export?format=doc") ;
Use this method to get the file content, I have used this method on a url that returned a CSV file upon hitting.

file_get_contents() how to fix error "Failed to open stream", "No such file"

I'm getting the following error when I try to run my PHP script:
failed to open stream: No such file or directory in C:\wamp\www\LOF\Data.php on line 3
script:
My code is as follows:
<?php
$json = json_decode(file_get_contents('prod.api.pvp.net/api/lol/euw/v1.1/game/by-summoner/20986461/recent?api_key=*key*'));
print_r($json);
?>
Note: *key* is a replacement for a string in the URL (my API key) and has been hidden for privacy reasons.
I removed the https:// from the URL to get one error to disappear.
Am I doing something wrong here? Maybe the URL?
The URL is missing the protocol information. PHP thinks it is a filesystem path and tries to access the file at the specified location. However, the location doesn't actually exist in your filesystem and an error is thrown.
You'll need to add http or https at the beginning of the URL you're trying to get the contents from:
$json = json_decode(file_get_contents('http://...'));
As for the following error:
Unable to find the wrapper - did you forget to enable it when you configured PHP?
Your Apache installation probably wasn't compiled with SSL support. You could manually try to install OpenSSL and use it, or use cURL. I personally prefer cURL over file_get_contents(). Here's a function you can use:
function curl_get_contents($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
Usage:
$url = 'https://...';
$json = json_decode(curl_get_contents($url));
Why don't you use cURL ?
$yourkey="your api key";
$url="https://prod.api.pvp.net/api/lol/euw/v1.1/game/by-summoner/20986461/recent?api_key=$yourkey";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$auth = curl_exec($curl);
if($auth)
{
$json = json_decode($auth);
print_r($json);
}
}
You may try using this
<?php
$json = json_decode(file_get_contents('./prod.api.pvp.net/api/lol/euw/v1.1/game/by-summoner/20986461/recent?api_key=*key*'));
print_r($json);
?>
The "./" allows to search url from current directory.
You may use
chdir($_SERVER["DOCUMENT_ROOT"]);
to change current working directory to root of your website if path is relative from root directory.
I just solve this by encode params in the url.
URL may be: http://abc/dgdc.php?p1=Hello&p2=some words
we just need to encode the params2.
$params2 = "some words";
$params2 = urlencode($params2);
$url = "http://abc/dgdc.php?p1=djkl&p2=$params2"
$result = file_get_contents($url);
just to extend Shankars and amals answers with simple unit testing:
/**
*
* workaround HTTPS problems with file_get_contents
*
* #param $url
* #return boolean|string
*/
function curl_get_contents($url)
{
$data = FALSE;
if (filter_var($url, FILTER_VALIDATE_URL))
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$data = curl_exec($ch);
curl_close($ch);
}
return $data;
}
// then in the unit tests:
public function test_curl_get_contents()
{
$this->assertFalse(curl_get_contents(NULL));
$this->assertFalse(curl_get_contents('foo'));
$this->assertTrue(strlen(curl_get_contents('https://www.google.com')) > 0);
}
We can solve this issue by using Curl....
function my_curl_fun($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$feed = 'http://................'; /* Insert URL here */
$data = my_curl_fun($feed);
The actual problem of this error has nothing to do with file_get_content, the problem is the requested url if the url is not throwing content of the page and redirecting the request to some where else file_get_content says "Failed to open stream", just before file_get_contents check whether the url is working and not redirecting, here is the code:
function checkRedirect404($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$out = curl_exec($ch);
// line endings is the wonkiest piece of this whole thing
$out = str_replace("\r", "", $out);
// only look at the headers
$headers_end = strpos($out, "\n\n");
if( $headers_end !== false ) {
$out = substr($out, 0, $headers_end);
}
$headers = explode("\n", $out);
foreach($headers as $header) {
if( substr($header, 0, 10) == "Location: " ) {
$target = substr($header, 10);
//echo "Redirects: $target<br>";
return true;
}
}
return false;
}
I hope below solution will work for you all as I was having the same problem with my websites...
For : $json = json_decode(file_get_contents('http://...'));
Replace with below query
$Details= unserialize(file_get_contents('http://......'));

Pass header/content-type from cURL-request to current output/header

I don't know how to write a better title. Feel free to edit. Somehow I didn't find anything on this:
I have a cURL request from PHP which returns a quicktime file. This works fine if I want to output the stream in the browser's window. But I want to send it as it were a real file. How can I pass the headers and set it to the script's output, without the need of storing everything in a variable.
The script looks like this:
if (preg_match('/^[\w\d-]{36}$/',$key)) {
// create url
$url = $remote . $key;
// init cURL request
$ch = curl_init($url);
// set options
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_NOBODY, false);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 256);
if (null !== $username) {
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
}
// execute request
curl_exec($ch);
// close
curl_close($ch);
}
I can see the header and content like this, so the request itself is working fine:
HTTP/1.1 200 OK X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2 Java/Oracle Corporation/1.7) Server: GlassFish Server Open Source Edition 3.1.2 Content-Type: video/quicktime Transfer-Encoding: chunked
Get the Content-Type from your curl query:
$info = curl_getinfo($ch);
$contentType = $info['content_type'];
And send it to the client:
header("Content-Type: $contentType");
Try this:
header ('Content-Type: video/quicktime');
before outputting the content
So with the help of the previous answers I got it to work. Still it has one request to much in my opinion, but maybe someone has a better approach.
The problems that occurred where:
1.) When using cURL like this:
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
the header didn't return the content-type, but only *\*.
2.) Using curl_setopt($ch, CURLOPT_NOBODY, false); got the right content-type but also the whole content itself. So I could store everything in a variable, read the header, send the content. Not really an option somehow.
So I had to request the header once using get_headers($url, 1); before getting the content.
3.) Finally, there was the problem that the HTML5-video-tag and the jwPlayer both didn't want to play 'index.php'. So with mod_rewrite and setting 'name.mov' to 'index.php' it worked:
RewriteRule ^(.*).mov index.php?_route=$1 [QSA]
This is the result:
if (preg_match('/^[\w\d-]{36}$/',$key)) {
// create url
$url = $remote . $key;
// get header
$header = get_headers($url, 1);
if ( 200 == intval(substr($header[0], 9, 3)) ) {
// create url
$url = $remote . $key;
// init cURL request
$ch = curl_init($url);
// set options
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
curl_setopt($ch, CURLOPT_NOBODY, false);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 256);
if (null !== $username) {
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
}
// set header
header('Content-Type: ' . $header['Content-Type']);
// execute request
curl_exec($ch);
// close
curl_close($ch);
exit();
}
}

grab file from php which forced to save as from another web server php with http authentication

i have a url from another server which having http auth enabled.
this specific url forces file to download a file.
I am trying here to grab the headers and set the headers back so that i can force the download from my php file after http auth done in curl, but no success. curl did not gave any error. nothing returned in $body.
$url=$_GET["url"];//another web server url which forcing file download save as
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_USERPWD, "username:password");//http auth done here
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, null);
curl_setopt($ch, CURLOPT_URL, $url);
$response = curl_exec($ch);
list ($headerString, $body) = explode("\r\n\r\n", $response, 2);
$headers = explode("\r\n", $headerString);
foreach ($headers as $header) {
header($header);
}
echo $body;
exit;
code above is working fine. Issue is just & in the $_GET["url"] which splitting valid url. just used urlencode and code working fine now. Hope this will help someone.

PHP cURL, read remote file and write contents to local file

I want to connect to a remote file and writing the output from the remote file to a local file, this is my function:
function get_remote_file_to_cache()
{
$the_site="http://facebook.com";
$curl = curl_init();
$fp = fopen("cache/temp_file.txt", "w");
curl_setopt ($curl, CURLOPT_URL, $the_site);
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_exec ($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
touch('cache/404_err.txt');
}else
{
touch('cache/'.rand(0, 99999).'--all_good.txt');
}
curl_close ($curl);
}
It creates the two files in the "cache" directory, but the problem is it does not write the data into the "temp_file.txt", why is that?
Actually, using fwrite is partially true.
In order to avoid memory overflow problems with large files (Exceeded maximum memory limit of PHP), you'll need to setup a callback function to write to the file.
NOTE: I would recommend creating a class specifically to handle file downloads and file handles etc. rather than EVER using a global variable, but for the purposes of this example, the following shows how to get things up and running.
so, do the following:
# setup a global file pointer
$GlobalFileHandle = null;
function saveRemoteFile($url, $filename) {
global $GlobalFileHandle;
set_time_limit(0);
# Open the file for writing...
$GlobalFileHandle = fopen($filename, 'w+');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FILE, $GlobalFileHandle);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, "MY+USER+AGENT"); //Make this valid if possible
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); # optional
curl_setopt($ch, CURLOPT_TIMEOUT, -1); # optional: -1 = unlimited, 3600 = 1 hour
curl_setopt($ch, CURLOPT_VERBOSE, false); # Set to true to see all the innards
# Only if you need to bypass SSL certificate validation
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
# Assign a callback function to the CURL Write-Function
curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'curlWriteFile');
# Exceute the download - note we DO NOT put the result into a variable!
curl_exec($ch);
# Close CURL
curl_close($ch);
# Close the file pointer
fclose($GlobalFileHandle);
}
function curlWriteFile($cp, $data) {
global $GlobalFileHandle;
$len = fwrite($GlobalFileHandle, $data);
return $len;
}
You can also create a progress callback to show how much / how fast you're downloading, however that's another example as it can be complicated when outputting to the CLI.
Essentially, this will take each block of data downloaded, and dump it to the file immediately, rather than downloading the ENTIRE file into memory first.
Much safer way of doing it!
Of course, you must make sure the URL is correct (convert spaces to %20 etc.) and that the local file is writeable.
Cheers,
James.
Let's try sending GET request to http://facebook.com:
$ curl -v http://facebook.com
* Rebuilt URL to: http://facebook.com/
* Hostname was NOT found in DNS cache
* Trying 69.171.230.5...
* Connected to facebook.com (69.171.230.5) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: facebook.com
> Accept: */*
>
< HTTP/1.1 302 Found
< Location: https://facebook.com/
< Vary: Accept-Encoding
< Content-Type: text/html
< Date: Thu, 03 Sep 2015 16:26:34 GMT
< Connection: keep-alive
< Content-Length: 0
<
* Connection #0 to host facebook.com left intact
What happened? It appears that Facebook redirected us from http://facebook.com to secure https://facebook.com/. Note what is response body length:
Content-Length: 0
It means that zero bytes will be written to xxxx--all_good.txt. This is why the file stays empty.
Your solution is absolutelly correct:
$fp = fopen('file.txt', 'w');
curl_setopt($handle, CURLOPT_FILE, $fp);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
All you need to do is change URL to https://facebook.com/.
Regarding other answers:
#JonGauthier: No, there is no need to use fwrite() after curl_exec()
#doublehelix: No, you don't need CURLOPT_WRITEFUNCTION for such a simple operation which is copying contents to file.
#ScottSaunders: touch() creates empty file if it doesn't exists. I think it was intention of OP.
Seriously, three answers and every single one is invalid?
You need to explicitly write to the file using fwrite, passing it the file handle you created earlier:
if ( $httpCode == 404 ) {
...
} else {
$contents = curl_exec($curl);
fwrite($fp, $contents);
}
curl_close($curl);
fclose($fp);
In your question you have
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
but from PHP's curl_setopt documentation notes...
It appears that setting CURLOPT_FILE before setting CURLOPT_RETURNTRANSFER doesn't work, presumably because CURLOPT_FILE depends on CURLOPT_RETURNTRANSFER being set.
So do this:
<?php
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FILE, $fp);
?>
not this:
<?php
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
?>
...stating "CURLOPT_FILE depends on CURLOPT_RETURNTRANSFER being set".
Reference: https://www.php.net/manual/en/function.curl-setopt.php#99082
To avoid memory leak problems:
I was confronted with this problem as well. It's really stupid to say but the solution is to set CURLOPT_RETURNTRANSFER before CURLOPT_FILE!
it seems CURLOPT_FILE depends on CURLOPT_RETURNTRANSFER.
$curl = curl_init();
$fp = fopen("cache/temp_file.txt", "w+");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FILE, $fp);
curl_setopt($curl, CURLOPT_URL, $url);
curl_exec ($curl);
curl_close($curl);
fclose($fp);
The touch() function doesn't do anything to the contents of the file. It just updates the modification time. Look at the file_put_contents() function.

Categories