views:

1723

answers:

6

I often find that I have files in my projects that need to be accessed from the file system as well as the users browser. One example is uploading photos. I need access to the files on the file system so that I can use GD to alter the images or move them around. But my users also need to be able to access the files from a URL like "site.com/uploads/myphoto.jpg".

Because the upload path usually corresponds to the URL I made up a function that seems to work most of the time. Take these paths for example:

File System /var/www/site.com/uploads/myphoto.jpg

URL http://site.com/uploads/myphoto.jpg

If I had a variable set to something like "/var/www/site.com/" then I could subtract it from the filesystem path and then use it as the URL to the image.

/**
 * Remove a given file system path from the file/path string.
 * If the file/path does not contain the given path - return FALSE.
 * @param   string $file
 * @param   string $path
 * @return  mixed
 */
function remove_path($file, $path = UPLOAD_PATH) {
    if(strpos($file, $path) !== FALSE) {
     return substr($file, strlen($path));
    }
}

$file = /var/www/site.com/uploads/myphoto.jpg;

print remove_path($file, /var/www/site.com/);
//prints "uploads/myphoto.jpg"

Does anyone know of a better way to handle this?

+3  A: 

Assume the directory is /path/to/root/document_root/user/file and the address is site.com/user/file

The first function I am showing will get the current file's name relative to the World Wide Web Address.

$path = $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];

and would result in:

site.com/user/file

The second function strips the given path of the document root.

$path = str_replace($_SERVER['DOCUMENT_ROOT'], '', $path)

Given I passed in /path/to/root/document_root/user/file, I would get

/user/file
Chacha102
considering that the unsanitized use of `$_SERVER['PHP_SELF']` could be harmful.
Sepehr Lajevardi
Yeah I figured that out the hard way when some fool hacked redditmirror.cc using that ;o Overwrote the damn config.php.
hopeseekr
It's funny that people still trust $_SERVER values. http://videos.code2design.com/video/play/PHP/11
Xeoncross
+2  A: 

IMHO such automation is really error prone. You're far better off using some explicit path helpers (eg. one for uploads, one for user pics, etc) or just encapsulate for example an uploaded file with a class.

// Some "pseudo code"
$file = UploadedFile::copy($_FILES['foo']);
$file->getPath(); // /var/www/example.org/uploads/foo.ext
$file->getUri();  // http://example.org/uploads/foo.ext
Philippe Gerber
I second this approach!
hopeseekr
A: 

More accurate way (including host port) would be to use this

function path2url($file, $Protocol='http://') {
    return $Protocol.$_SERVER['HTTP_HOST'].str_replace($_SERVER['DOCUMENT_ROOT'], '', $file);
}
George
A: 

Make it easy on yourself and just define the correct locations for both the filesystem and web folders and prepend the image filename with them.

Somewhere, you'd declare:

define('PATH_IMAGES_FS', '/var/www/example.com/uploads/');
define('PATH_IMAGES_WEB', 'uploads/');

Then you can just swap between paths depending on your need:

$image_file = 'myphoto.jpg';

$file = PATH_IMAGES_FS.$image_file;
//-- stores: /var/www/example.com/uploads/myphoto.jpg

print PATH_IMAGES_WEB.$image_file;
//-- prints: uploads/myphoto.jpg
random
Yes, I actually do use constants for the main locations - but I'm afraid this won't help as I don't know the location of the file until I fetch it. In other words, most in the base UPLOAD file or URL - but they might also be in subfolders or even somewhere else.
Xeoncross
Aaaah, didn't account for working with more than one location.
random
+1  A: 

Indeed, mine being the most elaborate suggestion thus far, I suspect it will be met with some criticism, however, I've it has proved to be versatile; effective with little error in most of my real-world testing environments. Rather than post one-half ton of code, here, I offer you export or checkout my web application SVN at ActiveState Firefly, where a component is implemented for precisely this purpose of Linux and Windows path to url conversion -- either via URL for automatic processing (i.e. via command line or as an "external tool", for example, from development environments-- where less useful system-paths are often sent from editors-- for sending URL's to a browser), or via HTML forms for manual processing.

Note: it is not necessary to export or checkout the entire app, if browsing the repo is preferrred-- Firefly affords the functionality to review source from the HTTP client. Please visit the following URL for details:

http://firefly.activestate.com/stanley.tweedle/anniedebrowsa/

Look for the file name path2url.phtml , where the URL _GET['winpath'] passes a *nix or Windows formatted path to the application, returning a clickable "link" to the desired location (in theory). Agreeable with other respondents, I propose this is /not/ the best solution, but it does work. I realize this solution might require tweaking to work with an existing application. Ideally, a more insightful developer than I might suggest some improvement upon my technique, that I might improve my own application as well.

Cheers, and good luck!

NoviceNotes.Net
A: 

$imgUrl = str_replace($_SERVER['DOCUMENT_ROOT'], '', $imgPath)

5teve23
$_SERVER is not safe to use without some form of parsing.
Xeoncross