簡體   English   中英

PHP - 將文件系統路徑轉換為 URL

[英]PHP - Convert File system path to URL

我經常發現我的項目中有需要從文件系統和用戶瀏覽器訪問的文件。 一個例子是上傳照片。 我需要訪問文件系統上的文件,以便我可以使用 GD 更改圖像或移動它們。 但我的用戶還需要能夠從 URL 訪問文件,例如example.com/uploads/myphoto.jpg

因為上傳路徑通常對應於 URL 我編了一個 function 似乎大部分時間都可以工作。 以這些路徑為例:

文件系統 /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"

有誰知道更好的方法來處理這個?

更准確的方法(包括主機端口)是使用這個

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

假設目錄是/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

恕我直言,這種自動化真的很容易出錯。 您最好使用一些顯式路徑助手(例如,一個用於上傳,一個用於用戶圖片等)或者只是封裝例如帶有類的上傳文件。

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

讓自己輕松一點,只需為文件系統和 web 文件夾定義正確的位置,並在圖像文件名前加上它們。

在某個地方,你會聲明:

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

我已經使用過它並與我一起工作:

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

嘗試這個:

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

例如,我使用這個將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;

下面的代碼有很好的注釋:

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

這個簡單的片段可以將文件路徑轉換為服務器上文件的 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);

我總是在本地開發環境中使用符號鏈接,@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"

因此,用HTTP_HOST替換DOCUMENT_ROOT不起作用。

我想出了這個小技巧:

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"

我認為即使我們不太可能在生產環境中使用符號鏈接,預防潛在的錯誤也是一種很好的做法。

這里的所有答案都促進 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

“將路徑轉換為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"

感謝George (以及 Stephanie 和 SWHarden 各自的評論)和Rid Iculous的回答,我得到了這個解決方案。

注意:我的解決方案沒有直接回答完整的問題,而是它的標題; 我想插入這個答案,因為它對那些在 Google 上搜索“php 將路徑轉換為 url”的人很有用

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM