PHP if file_exists() statement fails on file_get_content() from URL - php

I have a very simple function to read URL image file and save it on server.
function o99_download_shot_binary(){
$url = esc_url_raw( o99_get_content_link() ); // function returns http:// url
$img = $uploads['basedir'] . '/tmp/' . uniqid() . '.jpeg'; // name and location
file_put_contents($img, file_get_contents($url));
}
IT works ok, but sometimes , o99_get_content_link() returns an invalid URL, so an empty image is saved , so I made a simple check with if statement and separated the one liner:
function o99_download_shot_binary(){
$url = esc_url_raw( o99_get_content_link() ); // function returns http:// url
$img = $uploads['basedir'] . '/tmp/' . uniqid() . '.jpeg'; // name and location
$file = file_get_contents($url);
if (file_exists($file)) {
file_put_contents($img, $file);
}
}
But doing so, NO image is saved .
So I tried to change the if statement to
if ( $file) { file_put_contents($img, $file); }
..and now it works .
As everything is OK now, you might be wondering why did I posted this question , well,
since I want also to UNDERSTAND what I am doing - My Question is simply :
why does the file_exists($file) check fails ?
I assumed to myself (maybe wrongly) that it is because the file_exists() only checks LOCAL filesystem. If this is the case , then is there a dedicated function to check the existence over URL ? or any other better solutions for future references ?
EDIT I (as per comments request )
Var_dump() is a binary string :
string(51238) "����JFIF��������BZ�|su��{��3�_�R��[J��z���K�^��g�/��9���|*�F��W~�>񏎭tχ�>��� �&��?�~0�f�����[��i���R��_���g~�_��Ɵ�#����.5�x+�_ u��-�ٿ�L����ƺV�� ... ... ...
But this is predictable, like I said in original question, the file IS being saved OK, it is just a question of WHY the file_exists() check fails, and if there is a better way to perform that check on a binary remote file from URL...

$file = file_get_contents($url) means that $file contains a string, the contents of the file. Unless the file's contents happens to be a path to a file that exists, you won't save anything.
You want to check if( file_exists($url)) and keep the one-liner you had before.

file_exists() expects a path, like /home/user/foo.txt, or C:\foo.txt. You are supplying it with the contents of the file, not the local path to the file, so it will not return a true value (unless, of course, the contents of the file are a valid file path to an existing file... not to muddy the waters but it had to be said :) ).

Related

Replace save files if from same User

I have a directory called resale_certificates where I save files to but encrypt the name using parts of their email and codes assigned to them.
NOTE: The encryption is the same every time but unique to each user!
When they upload image.png it will save the file to theirEncrypt.png
If they upload another image.png it will replace theirEncrypt.png
However when they upload image.jpg now there will be theirEncrypt.jpg and theirEncrypt.png in the resale_certificates directory.
What is the best way to handle this? I'm looking for advice and open to changing how I'm saving it or tricks I could do to prevent this!
Thank You!
Well, you could use an image library to transform their uploaded image to whatever format you want, i.e. if they upload a .JPG you can use image libraries like Imagick or GD to output a .PNG file and upload those.
However, if you don't mind either the .JPG or .PNG ( or .GIF for that matter) you can scan the directory with PHP to look for all files ( can be really intensive though! ) to look for files with the name given.
For example:
<?php
foreach( scandir('/path/to/resale_certificates/') as $file ){
if( $file != '.' && $file != '..'){
// explode so we remove the last extension path ( not type safe ! )
$arguments = explode('.', $file);
// store the last part
$ext = end($arguments);
// pop the extension from the $arguments array so we are left
// with whatever was left
array_pop($arguments);
// concatenate the $arguments into a single string again
$filename = implode('.', $arguments);
// now we can check the filename again
if( $filename == $theirEncrypt){
unlink('/path/to/resale_certificates/' . $filename . '.' . $ext);
}
}
}
edit:
the $file is a string from the $files array returned by the scandir(); function. The single and double dot are a ways to navigate to the current (.) and the parent (..) directory and are therefore symlinks. Another option would be to check if the $file is actually a file. You could replace the comparison line with a is_file('/path/to/resale_certificates/' . $file) to check if it's a file or a symlink ( like the . and the .. ) but it's even more intensive then to check string comparison. In your usecase it is not neccesary.
On a related note, this is quite intensive, depending on the number of clients and certificates you have, you could, as an alternative, store the filename to storage (i.e. database or something similiar) and just unlink the file find there, this would save you to iterate over each file and simply unlink the file directly.
If you know a name of previously uploaded image then you can do the following before saving a new image:
<?php
$previousImageName = 'theirEncrypt.png';
unlink(APP_DIR . "/resale_certificates/" . $previousImageName);

check if php file exists on server

I'm looking for a way to see if a file exists on the local server. I would usually use if function exists but in this case it's not an option.
My question is how can I get number 2 to return true.
1.Returns true:
$acf_funcs = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/themes/vac3/acf/page_meta/functions.php';
var_dump(file_exists($acf_funcs));
2.Returns false:
$acf_funcs = 'http://vac3:8888/wp-content/themes/vac3/acf/page_meta/functions.php';
var_dump(file_exists($acf_funcs));
You can't use file_exists -- You'll need to use get_headers
$headers = get_headers('http://vac3:8888/wp-content/themes/vac3/acf/page_meta/functions.php', 1);
$file_found = stristr($headers[0], '200');
To check the local server filesystem, you need to get the path component from the URL:
var_dump(file_exists($_SERVER['DOCUMENT_ROOT'] . parse_url($acf_funcs, PHP_URL_PATH)));
In the above:
parse_url($acf_funcs, PHP_URL_PATH)
Returns: /wp-content/themes/vac3/acf/page_meta/functions.php and pre-pending $_SERVER['DOCUMENT_ROOT'] yields the same as your first example.
This will NOT however check if the file is available via http://vac3:8888.

Saving image file name exactly as URL image file into folder in PHP

I have visited this article previously and found it useful, but i would like to add more functionality to it by having it save an image file name according to the URL name.
This is what I've done so far and it works.
$contents=file_get_contents('http://www.domain.com/logo.png');
$save_path="C:/xampp/htdocs/proj1/download/[logo.png]";
file_put_contents($save_path,$contents);
Basically, where I have put square brackets around I want to have that dynamic based on the URL file name. For example, if i have an image url such as this: https://cf.dropboxstatic.com/static/images/brand/glyph-vflK-Wlfk.png, I would like it to save the image into the directory with that exact image name which in this case is glyph-vflK-Wlfk.png.
Is this possible to do?
I would do this way
$url = "http://www.domain.com/logo.png";
$file = file_get_contents($url);
$path = "C:/xampp/htdocs/proj1/download/". basename($url);
return !file_exists($path) ? file_put_contents($path, $file) : false;
From what I understand, what you're trying to do is the following :
$url = 'http://www.domain.com/logo.png';
$contents=file_get_contents($url);
$posSlash = strrpos($url,'/')+1);
$fileName = substr($url,$posSlash);
$save_path="C:/xampp/htdocs/proj1/download/".$fileName;
file_put_contents($save_path,$contents);
There is a function for that, basename():
$url="http://www.domain.com/logo.png";
$contents=file_get_contents($url);
$save_path="C:/xampp/htdocs/proj1/download/".basename($url);
file_put_contents($save_path,$contents);
You might want to check if it already exists with file_exists().

Avoid to rewrite a file that already exists

I write this simple code to save an image:
// $randomimage contains a random image url.
$content = file_get_contents($randomimage);
file_put_contents('images/'.$randomimage, $content);
I need a way to NOT rewrite an image with the same name. So, if an image with a certain name already exist in my /images/ folder, then do NOTHING.
It's simple but I don't know how to do that.
Sure, use file_exists.
$path = 'images/'.$randomimage;
if( !file_exists( $path)) {
// Note, see below
file_put_contents( $path, $content);
}
It is important to note that this inherently introduces a race condition into your program, as it is possible that another process could create the file in the time it takes you to check for its existence, then write to the file. In this case, you would overwrite the newly created file. However, it is highly unlikely, but possible.
In addition to nickb. is_file is better than file_exists, file_exists will return true on directories AND files.
So it would be:
if( !is_file ( 'images/'.$randomimage)) {
file_put_contents('images/'.$randomimage, $content);
}
PS: there is a function is_dir aswell, in case you were wondering.
http://php.net/manual/en/function.file-exists.php

How can I improve this PHP code?

I have the php code below which help me get a photo's thumbnail image path in a script
It will take a supplied value like this from a mysql DB '2/34/12/thepicture.jpg'
It will then turn it into this '2/34/12/thepicture_thumb1.jpg'
I am sure there is a better performance way of doing this and I am open to any help please
Also on a page with 50 user's this would run 50 times to get 50 different photos
// the photo has it is pulled from the DB, it has the folders and filename as 1
$photo_url = '2/34/12/thepicture_thumb1.jpg';
//build the full photo filepath
$file = $site_path. 'images/userphoto/' . $photo_url;
// make sure file name is not empty and the file exist
if ($photo_url != '' && file_exists($file)) {
//get file info
$fil_ext1 = pathinfo($file);
$fil_ext = $fil_ext1['extension'];
$fil_explode = '.' . $fil_ext;
$arr = explode($fil_explode, $photo_url);
// add "_thumb" or else "_thumb1" inbetween
// the file name and the file extension 2/45/12/photo.jpg becomes 2/45/12/photo_thumb1.jpg
$pic1 = $arr[0] . "_thumb" . $fil_explode;
//make sure the thumbnail image exist
if (file_exists("images/userphoto/" . $pic1)) {
//retunr the thumbnail image url
$img_name = $pic1;
}
}
1 thing I am curious about is how it uses pathinfo() to get the files extension, since the extension will always be 3 digits, would other methods of getting this value better performance?
Is there a performance problem with this code, or are you just optimizing prematurely? Unless the performance is bad enough to be a usability issue and the profiler tells you that this code is to blame, there are much more pressing issues with this code.
To answer the question: "How can I improve this PHP code?" Add whitespace.
Performance-wise, if you're calling built-in PHP functions the performance is excellent because you're running compiled code behind the scenes.
Of course, calling all these functions when you don't need to isn't a good idea. In your case, the pathinfo function returns the various paths you need. You call the explode function on the original name when you can build the file name like this (note, the 'filename' is only available since PHP 5.2):
$fInfo = pathinfo($file);
$thumb_name = $fInfo['dirname'] . '/' . $fInfo['filename'] . '_thumb' . $fInfo['extension'];
If you don't have PHP 5.2, then the simplest way is to ignore that function and use strrpos and substr:
// gets the position of the last dot
$lastDot = strrpos($file, '.');
// first bit gets everything before the dot,
// second gets everything from the dot onwards
$thumbName = substr($file, 0, $lastDot) . '_thumb1' . substr($file, $lastDot);
The best optimization for this code is to increase it's readability:
// make sure file name is not empty and the file exist
if ( $photo_url != '' && file_exists($file) ) {
// Get information about the file path
$path_info = pathinfo($file);
// determine the thumbnail name
// add "_thumb" or else "_thumb1" inbetween
// the file name and the file extension 2/45/12/photo.jpg
// becomes 2/45/12/photo_thumb.jpg
$pic1 = "{$path_info['dirname']}/{$path_info['basename']}_thumb.{$fil_ext}";
// if this calculated thumbnail file exists, use it in place of
// the image name
if ( file_exists( "images/userphoto/" . $pic1 ) ) {
$img_name = $pic1;
}
}
I have broken up the components of the function using line breaks, and used the information returned from pathinfo() to simplify the process of determining the thumbnail name.
Updated to incorporate feedback from #DisgruntledGoat
Why are you even concerned about the performance of this function? Assuming you call it only once (say, when the "main" filename is generated) and store the result, its runtime should be essentially zero compared to DB and filesystem access. If you're calling it on every access to re-compute the thumbnail path, well, that's wasteful but it's still not going to be significantly impacting your runtime.
Now, if you want it to look nicer and be more maintainable, that's a worthwhile goal.
The easiest way to fix this is to thumbnail all user profile pics before hand and keep it around so you don't keep resizing.
$img_name = preg_replace('/^(.*)(\..*?)$/', '\1_thumb\2', $file);
Edit: bbcode disappeared with \.

Categories