PHP - конвертировать путь к файловой системе в URL
Я часто обнаруживаю, что у меня есть файлы в моих проектах, к которым нужно получить доступ как из файловой системы, так и из браузера пользователей. Одним из примеров является загрузка фотографий. Мне нужен доступ к файлам в файловой системе, чтобы я мог использовать GD для изменения изображений или их перемещения. Но мои пользователи также должны иметь доступ к файлам с URL-адреса, например example.com/uploads/myphoto.jpg
.
Поскольку путь загрузки обычно соответствует URL-адресу, я создал функцию, которая, похоже, работает большую часть времени. Возьмите эти пути, например:
Файловая система /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"
Кто-нибудь знает, как лучше справиться с этим?
Ответы
Ответ 1
Предположим, что каталог /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
Более точный способ (включая порт хоста) заключается в использовании этого
function path2url($file, $Protocol='http://') {
return $Protocol.$_SERVER['HTTP_HOST'].str_replace($_SERVER['DOCUMENT_ROOT'], '', $file);
}
Ответ 3
ИМХО такая автоматизация действительно подвержена ошибкам. Вам гораздо лучше использовать некоторые явные помощники пути (например, один для загрузок, один для пользовательских фотографий и т.д.) Или просто инкапсулировать, например, загруженный файл с классом.
// 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
Ответ 4
Упростите себя и просто определите правильные местоположения как для файловой системы, так и для веб-папок и добавьте их вместе с ними.
Где-то, вы бы заявили:
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
Ответ 5
Попробуйте следующее:
$imgUrl = str_replace($_SERVER['DOCUMENT_ROOT'], '', $imgPath)
Ответ 6
Например, я использовал этот вариант для преобразования 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;
Ответ 7
Я использовал это и работал со мной:
$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));
Ответ 8
Этот простой фрагмент кода может преобразовать путь к файлу url на сервере. Некоторые параметры, такие как протокол и порт, должны быть сохранены.
$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);
Ответ 9
Код ниже хорошо прокомментирован:
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 not bother adding domain name here.
}
echo pathToURL('some/path/on/public/html');
Ответ 10
Я всегда использую символические ссылки в своей локальной среде разработки, а подход @George в этом случае завершается неудачно:
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"
Я считаю хорошей практикой предотвращать потенциальные ошибки, даже если мы вряд ли будем использовать символические ссылки в рабочей среде.
Ответ 11
Все ответы здесь поддерживают функцию str_replace(), которая заменяет все вхождения в любом месте строки, а не только в начале. preg_replace() убедится, что мы делаем точное совпадение только с начала строки:
function remove_path($file, $path = UPLOAD_PATH) {
return preg_replace("#^($path)#", '', $file);
}
Windows может быть проблемой, где разделители каталогов/и \. Убедитесь, что вы сначала заменили разделители каталогов:
function remove_path($file, $path = UPLOAD_PATH) {
$file = preg_replace("#([\\\\/]+)#", '/', $file);
$path = preg_replace("#([\\\\/]+)#", '/', $path);
return preg_replace("#^($path)#", '', $file);
}
Я бы поиграл с чем-то вроде следующего. Запишите realpath() и rtrim().
function webpath($file) {
$document_root = rtrim(preg_replace("#([\\\\/]+)#", '/', $_SERVER['DOCUMENT_ROOT']), '/');
$file = preg_replace("#([\\\\/]+)#", '/', realpath($file));
return preg_replace("#^($document_root)#", '', $file);
}
echo webpath(__FILE__); // Returns webpath to self
echo webpath('../file.ext'); // Relative paths
echo webpath('/full/path/to/file.ext'); // Full paths