One of the things new Kentico developers ask me a lot is how and where to access files from outside the CMS. Images, PDFs, videos, whatever you want a user to be able to download - on pretty much any website, users either need to be able to download them, or be kept from downloading them.
The Internal Ones
Kentico's own internal images are all managed from the App_Themes folder, in a subfolder "Images". These aren't exposed by default, and you shouldn't have to mess with these.
But this is the same location where, if you make a site with the same name, any files you put here will be automatically exported along with the site when you export it.
(There still isn't much you can do with these, and content editors can't access them, so I'd only put things that are commonly used sitewide and extremely unlikely to change over time here - font files or icons, for example)
Just because it's similar to the above, I'll mention that /CMSScripts/Custom is where you'd put any JS, or files related to JS packages (bootstrap, etc) - like the above, these aren't 'managed' by Kentico in any sense other than being exposed through the CMS, and it's entirely possible we'll lose CMS access to these in the future.
Media Library
The most interesting, and most commonly used, place to store anything in Kentico is the media library. The media libraries are a collection of subfolders that organize all of the media that you want Kentico to know about and be able to manage within the CMS. This generally involves any content images, banners, PDFs, videos, anything that you'd store in the filesystem, but want to actually manage or reference within the CMS.
Media library files are always stored in the database, but can be imported into Kentico, which lets them have a number of interesting properties:
- Users can be configured to be able to upload their own files - useful for media galleries, personal file collections, and other sorts of file uploads. Read more
- Can be given permissions for viewing
- Media library security is an all-or-none thing per folder - you set it up in IIS so that you can't access the files directly, then set it up in Kentico so it can only be viewed by users with certain roles/permissions, and then use Kentico's urls to access them. Read more
- They can be modified to a degree from within the Media Libraries application.
- When referenced by the appropriate URL (/GetMedia/), images can be downloaded at smaller sizes while preserving the original image.
Deeper dive
Database-wise, metadata about media library files (which have been imported) is stored in dbo.Media_File.
If you have files that aren't imported yet, they'll show up in the library (in the appropriate subfolder) but have a warning symbol and not have any of the permissions/configurations available, until you import them.
On the flip side, if you have imported a file, and then delete it from the filesystem, it'll just disappear from the interface, with no indication that it's still present. But then, if you go look in dbo.Media_File, it's actually still got a db record, taking up space. KInspector has a module that'll let you see these missing files, so you can either go into the DB and delete them, or better yet, create a dummy file in the filesystem, and use the Media Library interface to delete it properly.
In the filesystem, you set a base folder for all of your media libraries. If you don't set one up, ~/(Site name)/media is used - a separate folder per website. If you do set a custom name, then you can designate via a checkbox in the settings, whether to still have site-specific folders, or one big media library folder. Read more
So basically you have
//MediaLibraryBaseFolder/SiteName?/folder/image.filetype
And then there's a Thumbnails folder in each folder, that saves temporary files for when you've shrunk images with /GetMedia/
//MediaLibraryBaseFolder/SiteName?/folder/_thumbnails/imagethumbnail.filetype
Attachments
For most sitewide files, the media library is Kentico's recommended solution, but sometimes you want to be able to have media that moves around as you move a page, or that you can publish updates to the files. For that, we use attachments.
Attachments can be configured to either store them in the database, or in the filesystem, or both.
Essentially, if the settings say to store the file in the filesystem, it'll be stored in a foldder. If it says DB, then AttachmentBinary will be filled out in CMS_Attachment in the database, with the binary data of the file. (Setting it to both does both)
- The advantages of filesystem are performance, disadvantage is, it requires the Modify permission on the disk to be granted.
- The advantage of DB is the opposite: worse performance, due to needing to rebuild the file, but doesn't require the security edit. Storing it in the DB also gives you access to full-text search of your files, through Smart Search.
- Both does the best of both (good performance if security available, but still works if security not available, and smart search full-text search works), but requires the extra space inherent in storing a file in two places.
This setting is set in the Settings interface: System -> Files -> Storage. Similar to Media Library, the base path can be set to be site-specific or site-independent. Also, like Media Libraries, there's a default site-dependent path, if you don't set a custom path: ~/(Site name)/files
The Kentico Attachments interface (System: Files -> Attachments) lets you view all of your attachments, and even move files missing from one location (db or filesystem) to the other. (if it's set to DB only, you can't move it to the filesystem, and vice-versa)
Attachments come in three flavors, that are pretty much the same: They're added in the Attachments interface ('Unsorted' attachments), or through the Form tab ('Grouped' attachments), or submitted by users when they submit forms ('Form' attachments). A special subgroup of Form attachments also exists for items submitted as the Form data for a page of the 'CMS.File' pagetype: 'Page' Attachments.
Note that the Grouped attachments come in two datatypes: File (a single file per Form field), and Attachments (multiple files per Form field)
The only difference between these, really, is how they're represented in the database. 'Page' attachments have some extra logic related to referencing the page (via aliases) that that attachment 'is', but that's really more relevant to the *page type* than it is to the *attachment* itself.
The main advantage of attachments over documents (aside from Full-Text search in the smart-search) is that it's subject to document workflow and versioning. If your document uses workflow and/or versioning, the attachments will follow the same rules as their documents: if you save a change to an attachment, it won't apply until you publish the change to the document, and if you revert to a prior document version, that history's version of the attachment will likewise be restored.
Deeper dive
Attachments are easily discerned from media library files - not just by the folder they're in, but also their organization structure: Attachments are assigned guids instead of filenames/folders, and are instead put in a single-level folder based on the first two letters of their assigned guid.
So this would be:
//UploadedFiles/SiteName?/Guid-First-two/Attachmentguid.filetype
And for any resized versions:
//UploadedFiles/SiteName?/Guid-First-two/Attachmentguid_width_height.filetype
Form attachments are stored slightly differently:
//UploadedFormFiles/SiteName?/unknownguid.filetype/filename.filetype) (FormAttachment field on Form object - /unknownguid.filetype/filename.filetype)
In the database, you can tell the difference betwen the attachment types fairly easily:
- Unsorted attachments ('Properties' tab) have the flag AttachmentIsUnsorted = 1
- Grouped Attachments on Documents (Form tab)
- Attachments type: (AttachmentIsUnsorted = 0, AttachmentGroupGuid non-null)
- File type (AttachmentIsUnsorted = 0, AttachmentGroupGuid null)
For Grouped attachments of the 'Attachments' type, the guid matches the guid in [dbo].[CMS_Class].[ClassFormDefinition] for the page type / field they're attached to - it's encoded as part of the xml of that field.
Other spots where files are stored
- As mentioned above, attachments are affected by workflow and versioning. So, old versions of attachments are stored in ~/App_Data/VersionHistory/Attachments (not configurable)
- On opening a file's editor window in Kentico, a temp file is added to /App_Data/CMSTemp/ImageEditor/Guid-First-two/FileParentguid.filetype - Interestingly, this filename seems to have no relation to the primary file's Attachmentguid. A new one is created for the same file, each time you open Edit Image.
- In the database, these seem to be stored in dbo.Temp_file.
- The original item is modified directly when saved, so the CMSTemp ImageEditor records should be (as the folder name would imply) always safe to delete. I haven't checked what happens to the dbo.Temp_file record over time, but based on the name I have to imagine these are also pretty safe to delete.