Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
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?
Thanks.
Comments
Comment #1
Damien Tournoud CreditAttribution: Damien Tournoud commentedSomething like that will work:
But it will only work if the stream wrapper defines getLocalPath() (only public and private do that currently).
Comment #2
manfer CreditAttribution: manfer commentedI'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).
Comment #3
manfer CreditAttribution: manfer commentedThe 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.
Comment #5
lmeurs CreditAttribution: lmeurs commentedHi,
In Drupal 7/8 one can use
See http://api.drupal.org/api/drupal/includes--file.inc/function/drupal_real...
Comment #6
knalstaaf CreditAttribution: knalstaaf commentedCan you provide an example of this practice please?
This doesn't work for me:
(in a node.tpl.php)
It results in
Comment #7
knalstaaf CreditAttribution: knalstaaf commented<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.)
Comment #8
nevets CreditAttribution: nevets commentedUse file_create_url() instead of drupal_real_path()?
Comment #9
knalstaaf CreditAttribution: knalstaaf commentedThanks, 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?
Comment #10
13rac1 CreditAttribution: 13rac1 commentedProbably extra coding. Why does it matter if the domain name is listed? For most uses full URLs are better.
Comment #11
Everett Zufelt CreditAttribution: Everett Zufelt commentedComment #13
Anly Dcouth CreditAttribution: Anly Dcouth commentedHi,
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 .
Comment #14
Max_Headroom CreditAttribution: Max_Headroom commented#9
try file_uri_target
Comment #15
TravisCarden CreditAttribution: TravisCarden commentedRe #9: parse_url() would get you what you're actually after:
Comment #16
knalstaaf CreditAttribution: knalstaaf commentedExactly! Thanks!!
Comment #17
sirajs CreditAttribution: sirajs commentedSome 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:
Comment #18
hannanxp CreditAttribution: hannanxp commentedTry this..
Comment #19
robhoefakker CreditAttribution: robhoefakker commentedThis 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.
Comment #20
robhoefakker CreditAttribution: robhoefakker commentedMy bad, changed the title.
Comment #21
nevets CreditAttribution: nevets commentedIt would be better to use the API
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.
Comment #22
fedik CreditAttribution: fedik commentedI use for "public" (:
Comment #23
Gerben Zaagsma CreditAttribution: Gerben Zaagsma commentedI 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.
Comment #24
fedik CreditAttribution: fedik commentedin place where you need the relative path
Comment #25
Gerben Zaagsma CreditAttribution: Gerben Zaagsma commentedthanks!
Comment #26
kenorb CreditAttribution: kenorb commentedAPI for DrupalPublicStreamWrapper:
https://api.drupal.org/api/drupal/includes!stream_wrappers.inc/class/Dru...
See also:
http://drupal.stackexchange.com/questions/45299/why-drupal-realpathpubli...
http://drupal.stackexchange.com/questions/56487/how-do-i-get-the-path-fo...
Comment #27
merzikain CreditAttribution: merzikain commentedI'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:
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.
Example:
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.
Comment #28
Nicolas Bouteille CreditAttribution: Nicolas Bouteille commented#27 worked great thanks !
Comment #29
Altcom_Alan CreditAttribution: Altcom_Alan commented#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:
Comment #30
Nicolas Bouteille CreditAttribution: Nicolas Bouteille commentedswitched to #29 so that it can work on windows too. Works great too. Thanks.
Comment #31
samsterlin CreditAttribution: samsterlin commentedComment #32
Gik000 CreditAttribution: Gik000 commentedI can't believe it should be so hard to get a **** image from public:// url type! ...
Anyway $base_url will give the URL not the path!
Comment #33
kenorb CreditAttribution: kenorb commented@Gik000: Check How do I get the path for public://
Comment #34
David_Rothstein CreditAttribution: David_Rothstein commentedFor the original question, most of the answers here aren't correct in the general case. Using file_create_url() doesn't work because the URL returned by that function doesn't even have to be on the same server (think YouTube videos, CDNs, etc), and using $_SERVER['DOCUMENT_ROOT'] only works on certain server configurations (plus doesn't work at all for anything that would normally be stored outside the document root, such as private:// or temporary://)...
As described in the code comment, for files which aren't stored locally the original question (and the whole concept of "relative path") doesn't even apply, so that's what makes this a bit complicated in the general case.
Comment #36
dshumaker CreditAttribution: dshumaker commentedJust a side note / tid-bit for someone out there.
If you are using this code in say, a template file, then you might want to check the existence of the file before you "print" it. However the results of #34 David's code returns code that passes the file_exists php function but does not resolve correctly without a forward slash. Let my code explain:
So, notice the forward slashes added to the src and href string output lines above, and how I tried to add the forward slash to the file string passed to file_exists but that failed. The final result listed works.
Hopefully helpful.
-d
Comment #37
mforbes CreditAttribution: mforbes commentedIn case anyone stumbled here looking to make root-relative resource paths for things like img src values, here's some info. #36 above is almost there, but adding an initial "/" is not good in all cases because the whole site could be in a subdirectory of the docroot, like "http://example.com/my-site/". Therefore, we need to prepend "/my-site/" and not just "/". But how to find the string "/my-site/" (and just "/" if the site lives at the docroot)?
Let's say the file is "public://images/foo/jpg" so the path internal to the site is "sites/default/files/images/foo.jpg" and the root-relative path we desire is "/my-site/sites/default/files/images/foo.jpg".
Well, #15 above is great! The concern raised in #17 is mistaken because we are not passing "public://images/foo.jpg" to parse_url(), rather we are passing the output of file_create_url("public://images/foo.jpg"), so the 'path' element of the returned array will be just what we need. If you look at the code for file_create_url(), it basically just prepends $GLOBALS['base_url'] . '/' which in our case would be "http://example.com/my-site/", so then the remaining task is to lop off the "http://example.com" and parse_url() is the tool for the job:
It would be nice if we could bypass the absolute URL (with the scheme/host/port/etc) in the first place and just discover that "/my-site/" prefix alone. Fortunately, that's precisely what $GLOBALS['base_path'] is! (Aside: Complementing that is $GLOBALS['base_root'] which would just be "http://example.com".) So we could start with that and append the internal URL, which is to say append the file_public_path followed by the part after the "public://" (which can be stripped off trivially). Finding the file_public_path ("sites/default/files") is given in #22, #31, and #34 above, but #34 seems to have the best fallback so that's what I'll go with:
I'm not sure if the first way or the second way is "better." Both methods are naive in the case of external URLs as #34 mentions, and the only way I can think of to really plan for that would be to see if $GLOBALS['base_url'] is at the start of the string returned by file_create_url() like so:
If anybody has any comments on these methods, or an an even more "correct" way of getting a root-relative path, please chime in. My particular use-case is taking advantage of the fact that mimemail embeds images into multipart email messages only when the path is non-absolute, and the only non-absolute format that also renders reliably in a web browser is root-relative, so I basically need root-relative img tags if I want web previews of those email messages.
Comment #38
jdleonardHere's what worked for my needs. When added to mymodule.module (don't forget to clear the cache), this modifies all files using the public:// scheme to use relative paths.
Comment #39
doitDave CreditAttribution: doitDave commentedThanks, parse_url() was the missing link.
Comment #40
rahul_sankrit CreditAttribution: rahul_sankrit commented@jdleonard: Thanks, I tried this and it is working good for images but not working for Js and CSS files.
Change the Base URL:
Set the global variable called $base_url in sites/default/settings.php.
Comment #41
SivaprasadC CreditAttribution: SivaprasadC as a volunteer and at Drupal Partners for Innoppl Technologies Pvt. Ltd commentedComment #29 Works great to me. Thanks.