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!