PHP - конвертировать путь файловой системы в URL - PullRequest
25 голосов
/ 06 августа 2009

Я часто нахожу, что в моих проектах есть файлы, к которым нужно обращаться как из файловой системы, так и из браузера пользователя. Одним из примеров является загрузка фотографий. Мне нужен доступ к файлам в файловой системе, чтобы я мог использовать 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"

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

Ответы [ 11 ]

8 голосов
/ 06 августа 2009

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

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

$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
7 голосов
/ 06 августа 2009

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

function path2url($file, $Protocol='http://') {
    return $Protocol.$_SERVER['HTTP_HOST'].str_replace($_SERVER['DOCUMENT_ROOT'], '', $file);
}
6 голосов
/ 06 августа 2009

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

// 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
3 голосов
/ 07 августа 2009

Облегчите себе задачу, просто определите правильные места для файловой системы и веб-папок и добавьте к ним имя файла изображения.

Где-то вы бы заявили:

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
2 голосов
/ 15 сентября 2010

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

$imgUrl = str_replace($_SERVER['DOCUMENT_ROOT'], '', $imgPath)
1 голос
/ 16 марта 2015

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

$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));
1 голос
/ 19 ноября 2013

Например, я использовал это, чтобы преобразовать 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 голосов
/ 25 августа 2018

Все ответы здесь поддерживают функцию 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
0 голосов
/ 31 мая 2016

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

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"

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

0 голосов
/ 05 апреля 2016

Код ниже хорошо прокомментирован:

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');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...