PHP Saving and outputting GD Lib image - relative and absolute paths - php

I have a php script which generates an image using GD Lib, saves it to a predefined location. And then should output it.
My directory structure is like this:
www.example.com/projects/project-1/
Inside the project-1 directory I have these directories:
- /imgs/
- /js/
- /css/
- /php/
The script using GD Lib is in /php/ with another config.php script where the constants are defined. This is then included in the main script.
Say I have two constants:
define('SAVE_PATH', '/projects/project-1/imgs/'); //The image will not save - this does not work
define('OUTPUT_PATH', '/projects/project-1/imgs/'); //this works if there is an image in this location
I then save the image like so:
imagejpeg($im, SAVE_PATH.$name, 100);
I get the following error:
failed to open stream: No such file or directory in /public_html/projects/project-1/php/main.php
Is it possible to do this with just one constant that works for both saving and outputting?
I know I can't have an absolute save path like: http://www.example.com/projects/project-1/imgs/
And I know I can't have an absolute output path like: /public_html/projects/project-1/imgs/
So what is the most elegant solution to this problem?

Your issue is likely due to using absolute pathing in your SAVE_PATH. An absolute path begins with /, and a relative path does not. These will probably work:
define('SAVE_PATH', '../imgs/'); //path relative to the php script, assuming the php file isn't being included from another path
define('SAVE_PATH', '/public_html/projects/project-1/imgs/');
BUT
In efforts to make this more versatile, I would instead do the following. Set 2 constants, one for the base application directory, and one for the path to the image folder. The latter will be usable in conjunction with the former for the save path, and will be usable on its own as the output path:
//const instead of define is a little prettier, but this is a preference
const APPLICATION_PATH = '/projects/project-1';
const IMAGE_PATH = '/imgs/';
//Save the image - Absolute path to the file location
imagejpeg($im, APPLICATION_PATH.IMAGE_PATH.$name, 100);
//Echo the image url - Absolute path to the file url
echo "<img src='".IMAGE_PATH.urlencode($name)."' />";
You now only need to edit IMAGE_PATH to make changes to where the images reside which will appropriately affect both the system directory and the web url.

Related

How do I rename a php image that has a period (.) in the name

Im trying to rename an image that has a full stop in the name with php using the rename() function.
rename("images/cat.cute.jpg", "images/cute-cat.jpg");
Currently getting a "No such file or directory" error.
When you specify images/cat.cute.jpg, you are specifying a path relative to wherever your PHP script is actually executing. The error you are getting is simply telling you that there is no file called cat.cute.jpg in the folder images relative to the execution location of the script. Or, such a folder images does not exist. To fix this, you either need to specify the correct relative path, or you may specify an absolute path. Here is an example of using rename() with absolute paths:
rename("/images/cat.cute.jpg", "/images/cute-cat.jpg");
This assumes that there is an images/ folder relative to root, which may not be the case, but you can adjust as you need.

PHP opendir works fine with relative path and not with absolute one?

Here is the problem:
In one place I'm using relative path to load names of all files in certain folder:
if ($handle = opendir('images/uploads/form_id_1103/1'))
This is working fine, but if I change it to:
if ($handle = opendir('/images/uploads/form_id_1103/1'))
I get an error: No such file or directory in - just to mention, images folder is in the root, so /images should be valid
In the meantime, if I show an image from that ("non existing") folder with
<img src="/images/uploads/form_id_1103/1/test.jpg">
it works fine and shows the image.
I cannot use relative path, as I'm using Apache's mod_rewrite to transform URLs to SEO friendly ones.
You're confusing web URLs with file system paths. PHP's file-based functions dont' work with URLs, unless they're full+absolute http://blah/blah/blah/blah). You need to figure out the real path for your image on the server if you want to use an absolute one. It'd be something like
/home/site/example.com/docroot/images/etc...
^---url starts here.
If you start the path with a / on a Linux server. it will be processed as if you open the directory from the root of the linux installation. not relative to the current PHP file. a dot on the start of a path means the current directory.

How to upload a file using php to the parent directory

Hopefully easy question, I have a desktop application that allows the user to upload a file to a server using a form, the form sends the data to a protected file on the site like this. Site_root/protected_folder/myfile.php . If you use php file upload commands normally you'd be operating in the 'protected_folder' directory, which I don't want.
I want to add stuff to the images file on the root directory like this Site_root/images/ , how would you go about doing this without going the ftp root?
The usual method is to call move_uploaded_file(), where you set the destination path to your liking. The file name in $_FILES['tmp_name'] normally points to a temporary folder and it's subject to be removed without prior notice.
You can either use an absolute path like /path/to/images/ or use a relative path like ../images/
Assuming you're using move_uploaded_file the second paramater takes the directory that you wish to upload to. Perhaps showing you code may help if this post doesn't.
move_uploaded_file() will allow you to place uploads relative to the root directory if you simply start your path with a slash like
$newFileDir = '/username/public_html/websiteroot/subdir/yourfile.jpg';
move_uploaded_file($_FILES['postname']['tmp_name'],$newfileDir);
you can simply use copy() and double dot (../) in path to specify root directory to copy the uploaded file. I'm using the same. You may want to change the file name so that there will be unique filename in the directory error will occur. extension will also be same.
//
$filename = stripslashes($_FILES['postname']['name']);
$extension = getExtension($filename);
$newfilename ='photo_your_filename'.time().'.'.$extension;
$newFileDir = '../subdir/'.$newfilename;
copy($_FILES['postname']['tmp_name'],$newfileDir);

Properly navigating relative local paths in PHP

I'm having trouble specifically with the getimagesize function. I'm making the function call from /item/ajax/image.php relative to the domain's HTTP root. I'm trying to get the dimensions of an image stored at /portfolio/15/image.jpg. From what I understand, the function takes a filename as an argument, so I tried the following:
getimagesize('/portfolio/15/image.jpg')
And
getimagesize('../../portfolio/15/image.jpg')
But both of them just threw PHP errors.
try prefixing below to path:
$_SERVER['DOCUMENT_ROOT']
Relative paths always start from the file that is executed, which is most likely index.php. This is true for included files as well. This means in any file within you project relative paths start from your index.php. (Except a chdir() is done before)
I think it is really bad code to have paths like "../../file.ext" or the like. Define a Constant that has the full path to your application (eg: $_SERVER['DOCUMENT_ROOT']) and prepend it to any path you're using.
Example:
# somewhere in your index.php
define('ROOT_PATH', $_SERVER['DOCUMENT_ROOT']);
# in any included file
$my_path = ROOT_PATH."/portfolio/14/image.jpg"
This is imho the cleanest and most readable way to define paths.
In PHP "/" is not the same as the Apache "/" (web root). In PHP "/" refers to the system root. You should use paths relative to your PHP script location ('portfolio/15/image.jpg' if your script and the 'portfolio' folder are in the same location)
The filename you enter is not related to the http root but should be an existing path in the file system of your web server.
To see what goes wrong you could enter:
realpath('../../portfolio/15/image.jpg')
To see what directory you end up at.
Or use:
imagesize(dirname(__FILE__) . '/../../portfolio/15/image.jpg')
to get the full directory qualification.
As an alternative you can use the web address, but you should specify the full url:
getimagesize('http://yoursite.com/portfolio/15/image.jpg')
However, this is a slower option.

PHP: Saving files with PHP to different root directory?

OK when I save uploaded files with PHP via move_uploaded_file() I cannot use an absolute URL I have to use a relative one. My site has 2 root directories one for the http side and one for the https side: httpdocs and httpsdocs respectively. So if my script is on the https side how can I save the file to a location on the http side?
Thanks!
UPDATE
OK so it seems like I am using the wrong absolute path convention I am doing it like this:
$dir = 'https://www.mydomain.com/masonic_images/';
move_uploaded_file($_FILES['blue_image']['tmp_name'], $dir.$new_name);
move_uploaded_file() doesn't accept URLs for either parameter. The destination is an absolute path on your filesystem.
<?php
$dir = '/var/www/httpsdocs/'; // Adjust to your configuration
move_uploaded_file($_FILES['blue_image']['tmp_name'], $dir.$new_name);
As #apphacker suggested. you can use realpath(__FILE__) to determine the absolute path to a file.
If you cannot use the absolute path because you don't know what the absolute path is, use PHP's realpath() to figure out what it is and then use it.
Are the httpdocs and httpsdocs directories both located in the same parent folder? If so, just use a relative path for the second parameter in move_uploaded_file to place the file in the other root directory.
For example:
$uploaddir = '../httpdocs/';
$uploadfile = $uploaddir . basename($_FILES['myfile']['name']);
This code assumes that the uploading script is located in the httpsdocs root directory, and that you want to save the file into the httpdocs directory.
Note that since you put uploaded files inside httpdocs it could be possible to upload a php file and execute arbitrary code.

Categories