Je constate souvent dans mes projets que des fichiers doivent être accessibles à partir du système de fichiers ainsi que du navigateur de l'utilisateur. Un exemple est le téléchargement de photos. J'ai besoin d'accéder aux fichiers du système de fichiers pour pouvoir utiliser D.ieu afin de modifier les images ou de les déplacer. Mais mes utilisateurs doivent également pouvoir accéder aux fichiers à partir d'une URL telle que example.com/uploads/myphoto.jpg
.
Parce que le chemin de téléchargement correspond généralement à l'URL, j'ai créé une fonction qui semble fonctionner la plupart du temps. Prenons ces chemins par exemple:
Système de fichiers /Var/www/example.com/uploads/myphoto.jpg
Si j'avais une variable définie à quelque chose comme /var/www/example.com/
, je pourrais alors la soustraire du chemin du système de fichiers, puis l'utiliser comme URL de l'image.
/**
* 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"
Est-ce que quelqu'un connaît une meilleure façon de gérer cela?
Supposons que le répertoire est /path/to/root/document_root/user/file
et que l'adresse est site.com/user/file
La première fonction que je montre affichera le nom du fichier actuel par rapport à l’adresse Internet.
$path = $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
et aboutirait à:
site.com/user/file
La deuxième fonction supprime le chemin donné de la racine du document.
$path = str_replace($_SERVER['DOCUMENT_ROOT'], '', $path)
Étant donné que je passais en /path/to/root/document_root/user/file
, j'obtiendrais
/user/file
Un moyen plus précis (y compris le port de l’hôte) serait d’utiliser cette
function path2url($file, $Protocol='http://') {
return $Protocol.$_SERVER['HTTP_Host'].str_replace($_SERVER['DOCUMENT_ROOT'], '', $file);
}
IMHO Une telle automatisation est vraiment sujette aux erreurs. Vous feriez bien mieux d'utiliser des aides de chemin d'accès explicites (par exemple, un pour les téléchargements, un pour les images utilisateur, etc.) ou simplement encapsuler, par exemple, un fichier téléchargé avec une classe.
// 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
Simplifiez-vous la vie en définissant les emplacements corrects pour le système de fichiers et les dossiers Web et ajoutez-y le nom de fichier image.
Quelque part, vous déclareriez:
define('PATH_IMAGES_FS', '/var/www/example.com/uploads/');
define('PATH_IMAGES_WEB', 'uploads/');
Ensuite, vous pouvez simplement permuter les chemins en fonction de vos besoins:
$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
Essaye ça:
$imgUrl = str_replace($_SERVER['DOCUMENT_ROOT'], '', $imgPath)
J'ai utilisé cela et travaillé avec moi:
$file_path=str_replace('\\','/',__file__);
$file_path=str_replace($_SERVER['DOCUMENT_ROOT'],'',$file_path);
$path='http://'.$_SERVER['HTTP_Host'].'/'.$file_path;
Et si vous avez besoin du nom du répertoire au format url, ajoutez cette ligne:
define('URL_DIR',dirname($path));
Par exemple, j'ai utilisé celui-ci pour convertir C:\WAMP\WWW\myfolder\document.txt
en http://example.com/myfolder/document.txt
utiliser celui-ci:
$file_path=str_replace('\\','/',$file_path);
$file_path=str_replace($_SERVER['DOCUMENT_ROOT'],'',$file_path);
$file_path='http://'.$_SERVER['HTTP_Host'].$file_path;
Toutes les réponses ici promeuvent str_replace () qui remplace toutes les occurrences n'importe où dans la chaîne, pas seulement au début. preg_replace () s'assurera que nous ne faisons une correspondance exacte qu'au début de la chaîne:
function remove_path($file, $path = UPLOAD_PATH) {
return preg_replace("#^($path)#", '', $file);
}
Windows peut être un problème où les séparateurs de répertoires/et \. Assurez-vous de remplacer les séparateurs de répertoires en premier:
function remove_path($file, $path = UPLOAD_PATH) {
$file = preg_replace("#([\\\\/]+)#", '/', $file);
$path = preg_replace("#([\\\\/]+)#", '/', $path);
return preg_replace("#^($path)#", '', $file);
}
Je voudrais jouer avec quelque chose comme ce qui suit. Prenez note de realpath () et de 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
J'utilise toujours des liens symboliques dans mon environnement de développement local et l'approche de @ George échoue dans ce cas:
Le DOCUMENT_ROOT
est défini sur /Library/WebServer/Documents
et il existe un lien symbolique /Library/WebServer/Documents/repo1 -> /Users/me/dev/web/repo1
Supposons que les codes suivants sont dans /Users/me/dev/web/repo1/example.php
$_SERVER['DOCUMENT_ROOT'] == "/Library/WebServer/Documents" //default on OS X
tandis que
realpath('./some/relative.file') == "/Users/me/dev/web/repo1/some/relative.file"
Ainsi, remplacer DOCUMENT_ROOT
par HTTP_Host
ne fonctionnera pas.
Je viens avec ce petit truc:
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"
Je pense que c'est une bonne pratique d'éviter au préalable les bugs potentiels même si nous ne sommes pas susceptibles d'utiliser des liens symboliques dans un environnement de production.
Cet extrait peut convertir le chemin du fichier en URL du fichier sur le serveur. Certains paramètres tels que protocole et port doivent être conservés.
$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);
Le code ci-dessous est bien commenté:
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');