I'm trying to find the way to convert an uri like public://directory/file.ext to a relative path sites/default/files/directory/file.ext (of course this is an example because public:// could have other path) and I can't find the correct function in file API.

How to do it?



Something like that will work:

= file_uri_scheme($file);
if (
$scheme && file_stream_wrapper_valid_scheme($scheme)) {
$wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
$path = $wrapper->getLocalPath($file);

But it will only work if the stream wrapper defines getLocalPath() (only public and private do that currently).

I'm going to try to explain a little more because I'm not sure to understand if that is what I need.

The module where I need to use that relative path is a module that has on its configuration form upload file form elements. So it uploads the files and I have those file objects. I have to store on database and finally on the module output I need the url of the file to send it as a variable to a flash swf file. It is not valid for me an uri with schema (public://directory/file.ext) as output. And as it is a variable for flash, and I want to preserve the security on that flash that only allows local files, an absolute url like, http://example.com/sites/default/files/directory/file.ext, as returned by file_create_url, is not valid for me either.

On 6.x I was storing the filepath of the file object, $file->filepath, and that was fine for what I needed. It was something as sites/default/files/directory/file.ext, so on output I was using basepath() . check_url(filepath) and was the correct url I needed.

On 7.x I'm not sure how to proceed, I would like to continue storing the filepath, and proceed the same on output, but now in the file object I only have uri, and uri is public://directory/file.ext. (schema is going to be public always, public://directory is a constant on the module, is the directory where I upload the files). But I don't know how to create that relative filepath, how to obtain sites/default/files/directory/file.ext (or whatever it be, if public:// is other path. Example if public:// is only files, files/directory/file.ext).

Status:Closed (fixed)» Fixed

The absolute path returned by file_create_url is just fine to be used in flash vars and it is correctly in the same security sandbox. I pass it through urlencode before sending it to flash vars.

The problem I was experimenting was that I was doing a file move to the file object and I thought the file object uri was going to be updated with the new uri but it is not (I was storing then an incorrect uri), though the documentation says: "Move a file to a new location and update the file's database entry."

Reading that I was understanding the file object passed by reference and being updated but looking at the code it is not so, a new file object is returned.

As I don't really need the module uploaded files in database (I only need the files uploaded and uri stored on module table), I'm going to change code to unmanaged versions of file functions. Probably uploading files to temp and an unmanaged copy to my public://directory destination, then storing that uri, is the best solution for me.

Status:Active» Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.


In Drupal 7/8 one can use


See http://api.drupal.org/api/drupal/includes--file.inc/function/drupal_real...

Can you provide an example of this practice please?

This doesn't work for me:

= drupal_realpath($uri);
(in a node.tpl.php)

It results in

Notice: Array to string conversion in file_uri_scheme() (line 204 of /var/www/html/includes/file.inc).
Notice: Array to string conversion in drupal_realpath() (line 2190 of /var/www/html/includes/file.inc).

<a href="<?php print drupal_realpath($video_path); ?>>Watch video</a> works, but now the url looks like "/var/www/html/sites/default/files/flv/video-eng.flv". How do I get rid of /var/www/html/?

(#1 doesn't work either in my case.)

Status:Closed (fixed)» Active

Use file_create_url() instead of drupal_real_path()?

Thanks, that works but it includes the domain name (http://www.domain.com/sites/all/files/video.flv). Is it possible just to strip it down to sites/all/files/video.flv ? Or does that require extra coding?

Probably extra coding. Why does it matter if the domain name is listed? For most uses full URLs are better.

Status:Active» Fixed

Status:Fixed» Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Status:Fixed» Closed (fixed)


I have a similar issue. I want to categorize all the files according to their formats like jpg,jpeg files in Image folder; flv,mov in Videos folder and css file sin Css folder etc. Can you pls guide me in doing so..
In simple way...
I want my public:// -> sites/default/files to change to sites/default/files/DigitalLibray/Images for all image format files.
is there any module or do i ahve to add php code in the file .

Re #9: parse_url() would get you what you're actually after:

= file_create_url($field[0]['uri']);
$url = parse_url($url);
$path = $url['path'];

Exactly! Thanks!!

Some additional notes about parse_url.
Assuming the uri you are currently getting looks something like this: public://user1/node24/somefile.ext .... in example #15 $url=parse_url($url) returns an array with three elements:

$url['scheme'] = 'public'
$url['host'] = 'user1/'
$url['path'] = 'node24/somefile.ext'

Try this..

= file_stream_wrapper_get_instance_by_uri($uri);
$path = $wrapper->getDirectoryPath() . "/" . file_uri_target($uri);

Title:How can I convert a file uri to relative path?Visa versa
Version:7.x-dev» 7.15

This is the solution if you're trying to get the alias for a taxonomy term id (tid). In this case i'm using this in a view template, so $row['tid'] is the term id you want your alias for.

  $argtax_search = "taxonomy/term/".$row['tid'];
  $result = db_query('SELECT alias
  FROM url_alias WHERE source = :source', array(':source' => $argtax_search));
  foreach ($result as $record) {
       $part = $record->alias;
  $args2 = explode('/', $part);
  $alias = $args2[1];

Title:Visa versaHow can I convert a file uri to relative path?

My bad, changed the title.

It would be better to use the API

$alias = drupal_get_path_alias("taxonomy/term/".$row['tid']);

Though if one is building a link, it is better to use the l() function [For a url use url()], both will take care of aliasing for you.

I use for "public" (:

= str_replace('public:/', variable_get('file_public_path', 'sites/default/files'), $uri);

I am trying to do this too but where should I implement the snippets mentioned above. For example #22 in my theme template? Or settings.php? Forgive my ignorance but I am not a coder.

in place where you need the relative path


I've seen a ton of answers and talking in circles but haven't really seen a good, universal answer to the original question:

How can I convert a file uri to relative path?

The answer is incredibly simple and should fit ANY use case:

$realpath = drupal_realpath($uri);
$path = str_replace($_SERVER['DOCUMENT_ROOT'].'/','',$realpath);

Not every stream uri is going to be public:// or private://

I have custom modules that define their own stream wrappers and I'm certain other people do to. Using the above should work for any and all stream wrappers you encounter.

Say you have a stream wrapper for library:// that goes to files in {drupal_root}/sites/all/libraries

And say you have $uri = library://some_library/some_folder/some_image.jpg

Then $realpath = drupal_realpath($uri); makes $realpath = /var/www/html/drupal/sites/all/libraries/some_library/some_folder/some_image.jpg

And then $path = str_replace($_SERVER['DOCUMENT_ROOT'].'/','',$realpath); makes $path = sites/all/libraries/some_library/some_folder/some_image.jpg

Which means you end up with a relative path from a stream wrapper uri with very little code or processing overhead from loading unnecessary objects and such.

Issue summary:View changes

#27 worked great thanks !

#27 doesn't work on Windows as the slashes are different eg. drupal_realpath() returns "C:\folder\folder\file.ext" and $_SERVER['DOCUMENT_ROOT'] is set as "C:/folder" so no replacement happens.

Here's my take on how to create a relative path from a uri:

global $base_url;
$url = file_create_url($uri);
$url = str_replace($base_url .'/', '', $url);

switched to #29 so that it can work on windows too. Works great too. Thanks.