2009-08-06 2 views
25

Я часто обнаруживаю, что у меня есть файлы в моих проектах, к которым необходимо получить доступ из файловой системы, а также для браузера пользователей. Одним из примеров является загрузка фотографий. Мне нужен доступ к файлам в файловой системе, чтобы я мог использовать GD для изменения изображений или их перемещения. Но мои пользователи также должны иметь доступ к файлам с URL-адреса, например example.com/uploads/myphoto.jpg.PHP - преобразовать путь к файловой системе в URL

Поскольку путь загрузки обычно соответствует URL-адресу, я создал функцию, которая работает большую часть времени. Возьмите эти пути, например:

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

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

Если бы я имел набор переменных к чему-то например /var/www/example.com/, тогда я мог бы вычесть его из пути файловой системы, а затем использовать его как URL-адрес изображения.

/** 
* 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/example.com/uploads/myphoto.jpg; 

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

Кто-нибудь знает, как лучше справиться с этим?

+0

Спасибо. Хотя это может быть подвержено ошибкам, это именно то, что мне нужно в моем случае. –

ответ

8

Предположим, каталог /path/to/root/document_root/user/file и адрес site.com/user/file

Первая функция Я показываю получит имя текущего файла по отношению к World Wide Web Address.

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

и приведет:

site.com/user/file 

Вторая функция полосы заданного пути корня документа.

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

Учитывая я прошел в /path/to/root/document_root/user/file, я хотел бы получить

/user/file 
+2

, учитывая, что несаминированное использование '$ _SERVER ['PHP_SELF']' может быть вредным. – sepehr

+0

Да, я понял, что это было трудно, когда какой-то дурак взломал redditmirror.cc, используя это; o Переписал проклятый config.php. –

+0

Смешно, что люди по-прежнему доверяют значениям $ _SERVER. http://videos.code2design.com/video/play/PHP/11 – Xeoncross

6

ИМХО такой автоматизации действительно подвержен ошибкам. Вам гораздо лучше использовать некоторые явные помощники пути (например, один для загрузок, один для пользовательских фото и т. Д.) Или просто инкапсулировать, например, загруженный файл с классом.

// 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 
+0

Я второй такой подход! –

6

Более точный способ (включая порт хоста) будет использовать этот

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

return $ Protocol. $ _ SERVER ['HTTP_HOST']. Str_replace ($ _ SERVER ['DOCUMENT_ROOT'], '', realpath ($ file)); Добавление realpath очищает выходной URL правильно - wven, когда вход имеет ../ или ./ в пути. – ZTK

3

Сделать это легко на себя и просто определить правильные места для обеих файловых и веб-папок и предварять имя файла изображения с ними.

Где-то, вы бы объявить:

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

Тогда вы можете просто переключаться между путями в зависимости от ваших потребностей:

$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 
+0

Да, я действительно использую константы для основных мест - но я боюсь, что это не поможет, поскольку я не знаю, где находится файл, пока я его не заберу.Другими словами, большинство в базовом файле UPLOAD или URL-адресе - но они также могут быть в подпапках или даже где-то в другом месте. – Xeoncross

+0

Aaaah, не учитывал работу с несколькими местоположениями. – random

+0

Я думаю, что это лучший подход. Хорошее планирование облегчает жизнь. – Popsyjunior

2

Попробуйте это:

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

$ _SERVER небезопасно использовать без какой-либо разборки. – Xeoncross

1

Например, я использовал этот для преобразования C:\WAMP\WWW\myfolder\document.txt в http://example.com/myfolder/document.txt, используя этот:

$file_path=str_replace('\\','/',$file_path); 
$file_path=str_replace($_SERVER['DOCUMENT_ROOT'],'',$file_path); 
$file_path='http://'.$_SERVER['HTTP_HOST'].$file_path; 
0

Этот простой фрагмент кода может преобразовать путь к файлу на сервере. Некоторые настройки, такие как протокол и порт, должны быть сохранены.

 $filePath = str_replace('\\','/',$filePath); 
     $ssl = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? true : false; 
     $sp = strtolower($_SERVER['SERVER_PROTOCOL']); 
     $protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : ''); 
     $port = $_SERVER['SERVER_PORT']; 
     $stringPort = ((!$ssl && $port == '80') || ($ssl && $port == '443')) ? '' : ':' . $port; 
     $host = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']; 
     $fileUrl = str_replace($_SERVER['DOCUMENT_ROOT'] ,$protocol . '://' . $host . $stringPort, $filePath); 
1

Я использовал это и работал со мной:

$file_path=str_replace('\\','/',__file__); 
$file_path=str_replace($_SERVER['DOCUMENT_ROOT'],'',$file_path); 
$path='http://'.$_SERVER['HTTP_HOST'].'/'.$file_path; 

И если вам нужно имя каталога в формате URL-адреса добавьте следующую строку:

define('URL_DIR',dirname($path)); 
+0

ваш скрипт может не работать в других операционных системах, поэтому вместо него он должен быть постоянным пользователем DIRECTORY_SEPARATOR. – Popsyjunior

0

ниже код хорошо

function pathToURL($path) { 
    //Replace backslashes to slashes if exists, because no URL use backslashes 
    $path = str_replace("\\", "/", realpath($path)); 

    //if the $path does not contain the document root in it, then it is not reachable 
    $pos = strpos($path, $_SERVER['DOCUMENT_ROOT']); 
    if ($pos === false) return false; 

    //just cut the DOCUMENT_ROOT part of the $path 
    return substr($path, strlen($_SERVER['DOCUMENT_ROOT'])); 
    //Note: usually /images is the same with http://somedomain.com/images, 
    //  So let's not bother adding domain name here. 
} 
echo pathToURL('some/path/on/public/html'); 
0

Я всегда с нами е симлинки в моей локальной среде разработки и @ подхода Джорджа терпит неудачу в этом случае:

DOCUMENT_ROOT установлен в /Library/WebServer/Documents и есть символическая /Library/WebServer/Documents/repo1 -> /Users/me/dev/web/repo1

Предположим, что следующие коды в /Users/me/dev/web/repo1/example.php

$_SERVER['DOCUMENT_ROOT'] == "/Library/WebServer/Documents" //default on OS X 

в то время как

realpath('./some/relative.file') == "/Users/me/dev/web/repo1/some/relative.file" 

Таким образом, заменяя DOCUMENT_ROOT на HTTP_HOST не работает.

я придумал эту маленькую хитрость:

function path2url($path) { 
    $pos = strrpos(__FILE__, $_SERVER['PHP_SELF']); 
    return substr(realpath($path), $pos); 
} 

// where 
__FILE__       == "/Users/me/dev/web/repo1/example.php" 
$_SERVER['PHP_SELF']    ==    "/web/repo1/example.php" 
realpath("./some/relative.file") == "/Users/me/dev/web/repo1/some/relative.file" 
// If I cut off the pre-fix part from realpath($path), 
// the remainder will be full path relative to virtual host root 
path2url("./some/relative.file") ==    "/web/repo1/some/relative.file" 

Я думаю, что это хорошая практика, чтобы передние предотвратить возможные ошибки, даже мы, вероятно, не использовать символические ссылки в производственной среде.

Смежные вопросы