PHP - 将文件系统路径转换为URL

时间:2009-08-06 17:57:51

标签: php url filesystems

我经常发现我的项目中有文件需要从文件系统和用户浏览器访问。一个例子是上传照片。我需要访问文件系统上的文件,以便我可以使用GD来改变图像或移动它们。但我的用户还需要能够访问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 个答案:

答案 0 :(得分:8)

假设目录为/path/to/root/document_root/user/file且地址为site.com/user/file

我显示的第一个函数将获取当前文件相对于万维网地址的名称。

$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

答案 1 :(得分:7)

更准确的方式(包括主机端口)将使用此

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

答案 2 :(得分: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

答案 3 :(得分: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

答案 4 :(得分:2)

试试这个:

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

答案 5 :(得分: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;

答案 6 :(得分: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));

答案 7 :(得分: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);

答案 8 :(得分: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');

答案 9 :(得分:0)

我总是在本地开发环境中使用符号链接,@ 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"

我认为,即使我们不太可能在生产环境中使用符号链接,预防潜在的错误也是一种好习惯。

答案 10 :(得分:0)

这里的所有答案都促进了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