简体   繁体   English

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

[英]PHP - Convert File system path to URL

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.我需要访问文件系统上的文件,以便我可以使用 GD 更改图像或移动它们。 But my users also need to be able to access the files from a URL like example.com/uploads/myphoto.jpg .但我的用户还需要能够从 URL 访问文件,例如example.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.因为上传路径通常对应于 URL 我编了一个 function 似乎大部分时间都可以工作。 Take these paths for example:以这些路径为例:

File System /var/www/example.com/uploads/myphoto.jpg文件系统 /var/www/example.com/uploads/myphoto.jpg

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

If I had a variable set to something like /var/www/example.com/ then I could subtract it from the filesystem path and then use it as the URL to the image.如果我将变量设置为/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"

Does anyone know of a better way to handle this?有谁知道更好的方法来处理这个?

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);
}

Assume the directory is /path/to/root/document_root/user/file and the address is site.com/user/file假设目录是/path/to/root/document_root/user/file ,地址是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鉴于我传入了/path/to/root/document_root/user/file ,我会得到

/user/file

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

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.让自己轻松一点,只需为文件系统和 web 文件夹定义正确的位置,并在图像文件名前加上它们。

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

I've used this and worked with me:我已经使用过它并与我一起工作:

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

And if you need the directory name in url format add this line:如果您需要 url 格式的目录名称,请添加以下行:

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

尝试这个:

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

For example, i used this one to convert C:\\WAMP\\WWW\\myfolder\\document.txt to http://example.com/myfolder/document.txt use this one:例如,我使用这个将C:\\WAMP\\WWW\\myfolder\\document.txthttp://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;

The code below is well commented:下面的代码有很好的注释:

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');

This simple snippet can convert the file path to file's url on the server.这个简单的片段可以将文件路径转换为服务器上文件的 url。 Some settings like protocol and port should be kept.应该保留一些设置,如协议和端口。

        $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);

I always use symlinks in my local development environment and @George's approach fails in this case:我总是在本地开发环境中使用符号链接,@George 的方法在这种情况下失败:

The DOCUMENT_ROOT is set to /Library/WebServer/Documents and there is a symlink /Library/WebServer/Documents/repo1 -> /Users/me/dev/web/repo1 DOCUMENT_ROOT设置为/Library/WebServer/Documents并且有一个符号链接/Library/WebServer/Documents/repo1 -> /Users/me/dev/web/repo1

Assume that following codes are in /Users/me/dev/web/repo1/example.php假设以下代码在/Users/me/dev/web/repo1/example.php

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

while尽管

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

Thus, replacing DOCUMENT_ROOT with HTTP_HOST doesn't work.因此,用HTTP_HOST替换DOCUMENT_ROOT不起作用。

I come up with this little trick:我想出了这个小技巧:

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"

I think it's good practice to fore-prevent the potential bugs even we are not likely to use symlinks in production environment.我认为即使我们不太可能在生产环境中使用符号链接,预防潜在的错误也是一种很好的做法。

All answers here promotes str_replace() which replaces all occurences anywhere in the string, not just in the beginning.这里的所有答案都促进 str_replace() 替换字符串中任何位置的所有出现,而不仅仅是在开头。 preg_replace() will make sure we only do an exact match from the beginning of the string: preg_replace() 将确保我们只从字符串的开头进行精确匹配:

function remove_path($file, $path = UPLOAD_PATH) {
  return preg_replace("#^($path)#", '', $file);
}

Windows can be a problem where directory separators / and \\. Windows 可能会出现目录分隔符 / 和 \\ 的问题。 Make sure you replace the directory separators first:确保先替换目录分隔符:

function remove_path($file, $path = UPLOAD_PATH) {
  $file = preg_replace("#([\\\\/]+)#", '/', $file);
  $path = preg_replace("#([\\\\/]+)#", '/', $path);
  return preg_replace("#^($path)#", '', $file);
}

I would play with something like the following.我会玩类似以下的东西。 Make note of realpath() and rtrim().记下 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

One row complete solution to the "convert path to url" problem (*): “将路径转换为url”问题的一行完整解决方案(*):

$path = "/web/htdocs/<domain>/home/path/to/file/file.ext";

$url = ( ( isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' )? 'https://' : 'http://' ).$_SERVER['HTTP_HOST'].str_replace(realpath($_SERVER['DOCUMENT_ROOT']), '', realpath($ITEM_GPX_PATH));

echo $url;

// print "http(s)://<domain>/path/to/file/file.ext"

I came to this solution thanks to the answers of George (and the respective comments of Stephanie and SWHarden) and of Rid Iculous .感谢George (以及 Stephanie 和 SWHarden 各自的评论)和Rid Iculous的回答,我得到了这个解决方案。

Note: my solution does not answer the complete question directly, but its title;注意:我的解决方案没有直接回答完整的问题,而是它的标题; I thought to insert this answer because it can be useful to those who search on Google "php convert path to url"我想插入这个答案,因为它对那些在 Google 上搜索“php 将路径转换为 url”的人很有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM