Page Folders and Uploading of files in EPiServer

It is quite forward to get the uploaded file from the browser to the web server using ImageFileUpload component but where do you save the file in EPiServer? I wrote a post earlier about how to use the unified file system in EPiServer and this is the continuing…

The Concept of EPiServer Page Folders and Security

This is a very important feature in EPiServer. Each page in EPiServer can have a private folder to store files related to the page.

This folder is a normal folder with a numeric name. This number has nothing to do with the Page’s id – it is picked from its own sequence. The id of the page folder is stored in a property called PageFolderID on the page.

It is important to know that the security for a page folder comes from the page it belongs to. If you do not have the right to read the page you will not have the right to read the files in the page folder either. And creating the page folder and storing files in it is also is tied to the page security.

So what to do if you write code that needs a page folder and save a file in it if you are executing as an anonymous visitor?

Create page folder without UnauthorizedAccessException

The easiest way to to get the page folder from code is to call CurrentPage.GetPageDirectory(true) but it will only work if the folder already exist or if you are logged in as an editor with the right to create pages. This is how to do it your current user does not have the needed page access:

//Get the page folder ID
int folderId = (int)CurrentPage.Property["PageFolderID"].Value;

//Get the root directory for page folders
string pageDirectoryRootVirtualPath = VirtualPathHandler.PageDirectoryRootVirtualPath;
 
VersioningDirectory pageRootDirectory = (VersioningDirectory)GenericHostingEnvironment. VirtualPathProvider.GetDirectory(pageDirectoryRootVirtualPath);

//Combine the root path with folder name and get directory
string virtualPathFromFolderId = VirtualPathUtilityEx. Combine(pageDirectoryRootVirtualPath, VirtualPathUtility.AppendTrailingSlash(folderId.ToString()));

UnifiedDirectory pageDirectory = HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPathFromFolderId) as UnifiedDirectory;

//Bypass security and Create page folder if needed
if (pageDirectory == null)
{
    pageRootDirectory.BypassAccessCheck = true;
    pageDirectory = pageRootDirectory.CreateSubdirectory(folderId.ToString(), CurrentPage);
}
 

The important thing to notice above is that you can set the BypassAccessCheck property on files and folders. Since the file and folder objects are not cached new instances will be created so changing BypassAccessCheck only affects you instance of the object.

The same strategy can be applied to create a upload folder inside you page folder.

//Get or create upload folder in page folder
string uploadPath =  VirtualPathUtility.AppendTrailingSlash(Path.Combine(pageDirectory.VirtualPath, "upload"));

UnifiedDirectory uploadDirectory =  (UnifiedDirectory) GenericHostingEnvironment.VirtualPathProvider.GetDirectory(uploadPath);

if (uploadDirectory==null)
{
    pageDirectory.BypassAccessCheck = true;
    uploadDirectory = pageDirectory.CreateSubdirectory(UploadDirectoryName);
}

//Finally turn on BypassAccessCheck to allow everyone to upload.
uploadDirectory.BypassAccessCheck = true;

return uploadDirectory;


Change a files meta data using BypassAccessCheck

The method to use BypassAccessCheck can also be used to modify a file or its meta data if your code is running as a anonymous visitor.

//Get the file you want to change
UnifiedFile file = (UnifiedFile)GenericHostingEnvironment.VirtualPathProvider.GetFile(UploadedImage.ImageUrl);

//Bypass security
file.BypassAccessCheck = true;

//Modify meta data and save
file.Summary.Title = TitleTextBox.Text;
file.Summary.Author = AuthorTextBox.Text;
file.Summary.Subject = DescriptionTextBox.Text;
file.Summary.Dictionary[IsApproved] = "Y";
file.Summary.SaveChanges();

God luck with your upload function!

Bookmark and Share
  1. Per Edman’s avatar

    The GenericHostingEnvironment will be Obsolite in a near feature and BypassAccessCheck is ReadOnly – Do have any suggestions on how to workaround these issues?

    Reply

  2. Fredrik Haglund’s avatar

    Per, you should be able to use System.Web.Hosting.HostingEnvironment directly with the same result. I did not look at the documention for that class but it is not obsolete in the upcoming R2 release anyway…

    BypassAccessCheck property is read only on the VirtualPathProvider since it is configured from web.config but BypassAccessCheck can be read and written on UnifiedDirectory and UnifiedFile.

    /Fredrik

    Reply

  3. Christoffer Nordling’s avatar

    Hi Fredrik
    Have you found any way to access a folder that you do not have access to read the folder?
    I´ve added an upload function to xforms. The uploaded files are saved in a vpp folder and my thought was that they may want to remove everyones read rights on that folder. But that does not seem possible. GetUnifiedDirectory(folder); does not seem to have any way of bypassing the rights.

    by the way, thx for a great blog :)

    Reply

    1. Fredrik Haglund’s avatar

      Thanks!

      Obviously a little tricky to do that. I guess the only way is to impersonate a user with admin rights (that is a user that can access the EPiServer admin folder according to web.config) during that request.

      Change principal using PrincipalInfo.CurrentPrincipal in a try-finally block and be careful to restore the original.

      Reply

  4. Lei’s avatar

    when I got ur mail, I already did some tries, the problem now is, the file is surely uploaded to the vpp folder under the site, but it creates its own folder, and the Page File is actually empty, and then I create the folder from episerver editor mode and put a file then, physically, it creates another folder with the file in it, apparent that is the real page file folder, the one created by the code previously was wrong. so my question is how to create Page File folder and after uploading the file it could be accessed from Episerver’s file manager?

    —————————————————————————————–
    Origianl question:

    Hi Fredrik, got a few questions regarding to this:

    Basically, the requirement for my case is that an end user /visitor, can post an article and upload a photo with it, the image should be uploaded to the vpp folder and should be available in the Episerver File Managment, and when then page is deleted, the image should be deleted also. Your article mostly explains this question right?

    When uploading file to a page, the page has to be physically existed first right? In my case, it’s like put title, put test, upload a foto, then press the create button and create a page,so the upload foto is a step before the page is physically created, is it possible to do this? ok the trick will be put the upload code after the page creation code I guess?

    Normally, when end user uploading file is involved with a site, do we program a seperate unit or we do everything via Episerver’s file manager? Is there any exiting units we can use directly or we have to program ourselve like ur blog says?

    Reply

  5. Lei’s avatar

    Hej Fredrik

    I think I fixed all those problems now, so no need to reply :)

    Thank you very much for the article, they did helped a lot!!

    Reply

  6. Andreas Ek’s avatar

    EPiServer.Web.Hosting.GenericHostingEnvironment.VirtualPathProvider is missing in EPiServer 6.

    Reply

    1. Fredrik Fredrik Haglund’s avatar

      Nope, just add a reference to EPiServer.Framework assembly.

      Reply