2009-08-06 5 views
25

Często znajduję, że mam pliki w moich projektach, które muszą być dostępne z systemu plików, a także przeglądarki użytkowników. Jednym z przykładów jest przesyłanie zdjęć. Potrzebuję dostępu do plików w systemie plików, aby móc używać GD do modyfikowania obrazów lub przenoszenia ich. Ale moi użytkownicy muszą mieć także dostęp do plików z adresu URL, takiego jak example.com/uploads/myphoto.jpg.PHP - Konwertuj ścieżkę do systemu plików na URL

Ponieważ ścieżka przesyłania zwykle odpowiada adresowi URL, utworzyłem funkcję, która wydaje się działać przez większość czasu. Weź te ścieżki na przykład:

File System /var/www/example.com/uploads/myphoto.jpg

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

Gdybym miał zmienny zestaw do czegoś jak /var/www/example.com/, wtedy mógłbym odjąć go od ścieżki systemu plików, a następnie użyć go jako adresu URL obrazu.

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

Czy ktoś wie o lepszy sposób radzenia sobie z tym?

+0

Dzięki. Chociaż może to być podatne na błędy, jest to dokładnie to, czego potrzebuję w moim przypadku. –

Odpowiedz

8

Załóżmy, że katalog jest /path/to/root/document_root/user/file i adres jest site.com/user/file

Pierwsza funkcja pokazuję dostanie nazwę bieżącego pliku w stosunku do World Wide Web Address.

$path = $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF']; 

i spowoduje:

site.com/user/file 

Druga funkcja taśmy daną ścieżkę korzenia dokumentu.

$path = str_replace($_SERVER['DOCUMENT_ROOT'], '', $path) 

Biorąc mijałem w /path/to/root/document_root/user/file, chciałbym dostać

/user/file 
+2

biorąc pod uwagę, że nieautoryzowane użycie '$ _SERVER ['PHP_SELF']' może być szkodliwe. – sepehr

+0

Tak, wymyśliłem to na własnej skórze, gdy jakiś głupiec zhakował redditmirror.cc, używając tego, o Overwrote the damn config.php. –

+0

To zabawne, że ludzie wciąż ufają wartościom $ _SERVER. http://videos.code2design.com/video/play/PHP/11 – Xeoncross

6

IMHO taki Automation jest naprawdę podatne na błędy. Znacznie lepiej jest użyć pomocników o wyraźnej ścieżce (np. Jeden do przesłania, jeden do zdjęć użytkownika itp.) Lub po prostu zamknąć na przykład przesłany plik z klasą.

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

Podsumowując to podejście! –

6

Bardziej dokładny sposób (w tym portu hosta) byłoby użyć tego

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

return $ Protocol. $ _ SERVER ['HTTP_HOST']. Str_replace ($ _ SERVER ['DOCUMENT_ROOT'], '', realpath (plik $)); Dodanie adresu realpath wyczyść poprawnie wyjściowy adres URL - w przypadku, gdy dane wejściowe mają znak ./ lub ./ w ścieżce. – ZTK

3

Ułatw na siebie i po prostu zdefiniować odpowiednie lokalizacje zarówno dla systemu plików i internetowych katalogów i poprzedzić nazwę pliku obrazu z nimi.

Gdzieś chcesz zadeklarować:

define('PATH_IMAGES_FS', '/var/www/example.com/uploads/'); 
define('PATH_IMAGES_WEB', 'uploads/'); 

Wtedy można tylko przełączać się między ścieżkami w zależności od potrzeb:

$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 
+0

Tak, faktycznie używam stałych dla głównych lokalizacji - ale obawiam się, że to nie pomoże, ponieważ nie znam lokalizacji pliku, dopóki go nie pobiorę.Innymi słowy, większość w bazowym pliku UPLOAD lub adresie URL - ale mogą one również znajdować się w podfolderach, a nawet w innych miejscach. – Xeoncross

+0

Aaaah, nie uwzględniał pracy z więcej niż jedną lokalizacją. – random

+0

Myślę, że to najlepsze podejście. Dobre planowanie ułatwia życie. – Popsyjunior

2

Spróbuj tego:

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

$ _SERVER nie jest bezpieczne w użyciu bez jakiejś formy analizowania. – Xeoncross

1

Na przykład, użyłem tego do konwersji C:\WAMP\WWW\myfolder\document.txt na http://example.com/myfolder/document.txt użyj tego:

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

Ten prosty fragment może przekonwertować ścieżkę pliku na adres pliku na serwerze. Niektóre ustawienia, takie jak protokół i port, powinny być przechowywane.

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

Używałem tego i pracował ze mną:

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

A jeśli potrzebujesz nazwę katalogu w formacie url dodać ten wiersz:

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

Twój skrypt może nie działać na innych systemach operacyjnych, więc stała użytkownika DIRECTORY_SEPARATOR zamiast jawnie. – Popsyjunior

0

Poniższy kod jest dobrze skomentował:

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

Zawsze nas dowiązania e w moim lokalnym środowisku programistycznym i @ podejście George'a nie w tym przypadku:

DOCUMENT_ROOT jest ustawiony na /Library/WebServer/Documents i jest dowiązaniem /Library/WebServer/Documents/repo1 -> /Users/me/dev/web/repo1

Załóżmy, że następujące kody w /Users/me/dev/web/repo1/example.php

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

natomiast

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

W ten sposób zastępując DOCUMENT_ROOT przez HTTP_HOST nie działa.

wymyślić ten mały 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" 

myślę, że to dobra praktyka, aby przednie-zapobiec potencjalnych błędów nawet nie jesteśmy skłonni do korzystania dowiązania w środowisku produkcyjnym.