I wrote a PHP script that allows me to get the dimensions (width and height) of a remotely hosted JPG without having to download it in full (just the first 10K).
The problem with this is I write the partial download to a file, then read that file to extract the information I need (using getImageSize).
I know this can be down without writing to disk, but I do not know how.
Anyone have suggestions/solutions?
Here is my original code:
function remoteImage($url){
$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch, CURLOPT_RANGE, "0-10240");
$fn = "partial.jpg";
$raw = curl_exec($ch);
$result = array();
if(file_exists($fn)){
unlink($fn);
}
if ($raw !== false) {
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status == 200 || $status == 206) {
$result["w"] = 0;
$result["h"] = 0;
$fp = fopen($fn, 'x');
fwrite($fp, $raw);
fclose($fp);
$size = getImageSize($fn);
if ($size===false) {
// Cannot get file size information
} else {
// Return width and height
list($result["w"], $result["h"]) = $size;
}
}
}
curl_close ($ch);
return $result;
}
My original question, which lead to this, is here - and might be helpful.
It may be possible to use a memory file stream.
$fn = 'php://memory';
See: http://php.net/manual/en/wrappers.php.php
Related
I want to make filesize(), a dynamic filesize. What does it mean?
I mean, when I give it a link and the link is dynamic, too.
The filesize() will calculate the size of file in Kb, Mb and Gb.
My link is dynamic I just want the filesize() in converted of Mb and Gb. I want it for URLs.
This will do the trick
You can also pass a precision, maybe you want this to be 0.
<?php
function human_filesize($size, $precision = 2) {
$units = ['B','kB','MB','GB','TB','PB','EB','ZB','YB'];
$step = 1024;
$i = 0;
while (($size / $step) > 0.9) {
$size = $size / $step;
$i++;
}
return round($size, $precision).$units[$i];
}
function getFileSizeFromUrl($url){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
$data = curl_exec($ch);
$size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
curl_close($ch);
return human_filesize($size);
}
echo getFileSizeFromUrl(" YOUR URL HERE ");
I have some cURL call that download a large file.
I'm wondering if it is possible to calculate hash when the file is still downloading?
I think the progress callback function is the right place for accomplish that..
function get($urlget, $filename) {
//Init Stuff[...]
$this->fp = fopen($filename, "w+");
$ch = curl_init();
//[...] irrelevant curlopt stuff
curl_setopt($ch, CURLOPT_FILE, $this->fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, array($this,'curl_progress_cb'));
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$ret = curl_exec($ch);
if( curl_errno($ch) ){
$ret = FALSE;
}
curl_close($ch);
fclose($this->fp);
return $ret;
}
function curl_progress_cb($dltotal, $dlnow, $ultotal, $ulnow ){
//... Calculate MD5 of file here with $this->fp
}
Its possible to calculate md5 hash of partially downloaded file, but it does not make too much sense. Every downloaded byte will change your hash diametrally, what is the reason behind going with this kind solution?
If you need to have md5 hash for entire file than the answer is NO. Your program has to first download the file and then generate the hash.
I just do it:
in a file wget-md5.php, add the below code:
<?php
function writeCallback($resource, $data)
{
global $handle;
global $handle_md5_val;
global $handle_md5_ctx;
$len = fwrite($handle,$data);
hash_update($handle_md5_ctx,$data);
return $len;
}
$handle=FALSE;
$handle_md5_val=FALSE;
$handle_md5_ctx=FALSE;
function wget_with_curl_and_md5_hashing($url,$uri)
{
global $handle;
global $handle_md5_val;
global $handle_md5_ctx;
$handle_md5_val=FALSE;
$handle_md5_ctx=hash_init('md5');
$handle = fopen($uri,'w');
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_BUFFERSIZE, 64000);
curl_setopt($curl, CURLOPT_WRITEFUNCTION, 'writeCallback');
echo "wget_with_curl_and_md5_hashing[".$url."]=downloading\n";
curl_exec($curl);
curl_close($curl);
fclose($handle);
$handle_md5_val = hash_final($handle_md5_ctx);
$handle_md5_ctx=FALSE;
echo "wget_with_curl_and_md5_hashing[".$url."]=downloaded,md5=".$handle_md5_val."\n";
}
wget_with_curl_and_md5_hashing("http://archlinux.polymorf.fr/core/os/x86_64/core.files.tar.gz","core.files.tar.gz");
?>
and run:
$ php -f wget-md5.php
wget_with_curl_and_md5_hashing[http://archlinux.polymorf.fr/core/os/x86_64/core.files.tar.gz]=downloading
wget_with_curl_and_md5_hashing[http://archlinux.polymorf.fr/core/os/x86_64/core.files.tar.gz]=downloaded,md5=5bc1ac3bc8961cfbe78077e1ebcf7cbe
$ md5sum core.files.tar.gz
5bc1ac3bc8961cfbe78077e1ebcf7cbe core.files.tar.gz
I need to give my images an extension, depending on their type and also create a completely new name for them. Can I get the extension before I send the file to the server?
$_POST['image'] is a URL of an image. $new_name is supposed to be added while running the switch.
$image = $_POST['image'];
$ch = curl_init($image);
curl_setopt($ch, CURLOPT_HEADER, 0);
$imagedata = curl_exec($ch);
list($width, $height, $type) = getimagesize($filename);
switch ($type) {
case 1: ....... //Give the filename a .gif extension and so on for every filetype
}
$fp = fopen('../images/' . $new_name, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_close($ch);
fclose($fp);
!FOUND ANSWER! (sorry if I'm answering my own question wrong (in means of simply "editing" the question), comment on how to do it correctly, if I'm wrong ;)
I simply need to run the cURL function 2 times, but with different names. The first one simply gets me the info about the file, and the second one saves it wit the $new_name
$image = $_POST['image'];
$ch = curl_init($image); curl_setopt($ch, CURLOPT_HEADER, 0);
$imagedata = curl_exec($ch); $info = curl_getinfo($ch,
CURLINFO_CONTENT_TYPE); curl_close($ch);
if($info == "image/jpeg") //Running a code that will give the image an
appropriate extension...
$cf = curl_init($image); $fp = fopen('../images/' . "image.jpg",
'wb'); curl_setopt($cf, CURLOPT_FILE, $fp); curl_exec($cf);
curl_close($cf); fclose($fp);
I am using following code to download files from some remote server using php
//some php page parsing code
$url = 'http://www.domain.com/'.$fn;
$path = 'myfolder/'.$fn;
$fp = fopen($path, 'w');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
$data = curl_exec($ch);
curl_close($ch);
fclose($fp);
// some more code
but instead of downloading and saving the file in the directory it is showing the file contents (junk characters as file is zip) directly on the browser only.
I guess it might be an issue with header content, but not know exactly ...
Thanks
I believe you need:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
to make curl_exec() return the data, and:
$data = curl_exec($ch);
fwrite($fp, $data);
to get the file actually written.
As mentioned in http://php.net/manual/en/function.curl-setopt.php :
CURLOPT_RETURNTRANSFER: TRUE to return the transfer as a string of the return value of curl_exec() instead of outputting it out directly.
So you can simply add this line before your curl_exec line:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
and you will have the content in $data variable.
Use the following function that includes error handling.
// Download and save a file with curl
function curl_dl_file($url, $dest, $opts = array())
{
// Open the local file to save. Suppress warning
// upon failure.
$fp = #fopen($dest, 'w+');
if (!$fp)
{
$err_arr = error_get_last();
$error = $err_arr['message'];
return $error;
}
// Set up curl for the download
$ch = curl_init($url);
if (!$ch)
{
$error = curl_error($ch);
fclose($fp);
return $error;
}
$opts[CURLOPT_FILE] = $fp;
// Set up curl options
$failed = !curl_setopt_array($ch, $opts);
if ($failed)
{
$error = curl_error($ch);
curl_close($ch);
fclose($fp);
return $error;
}
// Download the file
$failed = !curl_exec($ch);
if ($failed)
{
$error = curl_error($ch);
curl_close($ch);
fclose($fp);
return $error;
}
// Close the curl handle.
curl_close($ch);
// Flush buffered data to the file
$failed = !fflush($fp);
if ($failed)
{
$err_arr = error_get_last();
$error = $err_arr['message'];
fclose($fp);
return $error;
}
// The file has been written successfully at this point.
// Close the file pointer
$failed = !fclose($fp);
if (!$fp)
{
$err_arr = error_get_last();
$error = $err_arr['message'];
return $error;
}
}
I have tried to download an image from a PHP link. When I try the link in a browser it downloads the image. I enabled curl and I set “allow_url_fopen” to true. I’ve used the methods discussed here Saving image from PHP URL but it didn’t work. I've tried "file_get_contents" too, but it didn't work.
I made few changes, but still it doesn’t work. This is the code
$URL_path='http://…/index.php?r=Img/displaySavedImage&id=68';
$ch = curl_init ($URL_path);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
$raw=curl_exec($ch);
curl_close ($ch);
$fp = fopen($path_tosave.'temp_ticket.jpg','wb');
fwrite($fp, $raw);
fclose($fp);
Do you have any idea to make it works? Please help. Thanks
<?php
if( ini_get('allow_url_fopen') ) {
//set the index url
$source = file_get_contents('http://…/index.php?r=Img/displaySavedImage&id=68');
$filestr = "temp_ticket.jpg";
$fp = fopen($filestr, 'wb');
if ($fp !== false) {
fwrite($fp, $source);
fclose($fp);
}
else {
// File could not be opened for writing
}
}
else {
// allow_url_fopen is disabled
// See here for more information:
// http://php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen
}
?>
This is what I used to save an image without an extension (dynamic image generated by server). Hope it works for you. Just make sure that the file path location is fully qualified and points to an image. As #ComFreek pointed out, you can use file_put_contents which is the equivalent to calling fopen(), fwrite() and fclose() successively to write data to a file. file_put_contents
You can use it as a function :
function getFile($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$tmp = curl_exec($ch);
curl_close($ch);
if ($tmp != false){
return $tmp;
}
}
And to call it :
$content = getFile(URL);
Or save its content to a file :
file_put_contents(PATH, getFile(URL));
You're missing a closing quote and semicolon on the first line:
$URL_path='http://…/index.php?r=Img/displaySavedImage&id=68';
Also, your URL is in $URL_path but you initialise cURL with $path_img which is undefined based on the code in the question.
Why use cURL when file_get_contents() does the job?
<?php
$img = 'http://…/index.php?r=Img/displaySavedImage&id=68';
$data = file_get_contents( $img );
file_put_contents( 'img.jpg', $data );
?>