Last updated January 21, 2014. Created on December 1, 2009.
Edited by Fiable.biz, RLK, cedewey, davidneedham. Log in to edit this page.

The File module enables you to upload and attach files to content and to manage these uploads if you have the appropriate permissions. This module is responsible for validating file content and managing uploaded files. It also provides options for displaying file content.

As a site administrator you will be able to control what type of files can be uploaded and their maximum size.

File module provides its functionality by defining a File field type for the Field module. File attachments are defined at the content type level (or other entities). To learn how to define a field and add it to a content type, see Working with Field UI.

Uses

Adding a file field to a content type

Navigate to the "Manage fields" tab of the content type to which you wish to add the file field (Administer > Structure > Content types, and the link manage fields for your specific content type).

Select the field type file, give the field a label and machine name, click-and-drag it to the place you want to have it among your fields, and hit the save button.

As when adding any new field, you are first required to set the field specific settings. These apply for all places where you use the field. These cannot be changed per entity.

  • When checked, the Enable Display field option allows users to choose if a file should be shown when viewing the content.
  • The Files displayed by default option makes the display file option checked by default, when users upload files to this field.
  • The Upload destination by default only has the public files option available – making the files available right from the server (without Drupal checking any access). If you want to use private files, you must first change some settings at the file system administration page (Administer > Configuration > Media: File system). See below for details.

The next step is to set the field settings for this instance only. This can be changed between different content types (or other entities).

You can add validation options for the File field when you configure the content type. You must list all of the file extensions that the final user will need to be able to upload. The optional file directory where the files will be uploaded is a sub-directory of the file system path defined in the file system administration page (Administer > Configuration > Media: File system). You may specify a maximum file size for each file uploaded.


Managing attachment display

Once a file has been attached to content, you can specify whether it will be displayed in the list of attached files or not. Listed files are displayed automatically in a section at the bottom of the content; non-listed files can for example be embedded in your content, but are not included in the list. (Embedding a file in your content means you copy the path of the file and manually embed it where you want, for example, to insert in the content as a link tag. Note that the text format "Filtered HTML" by default refuses any image tags..)

Additional options for managing the display of the file list are available in the "Manage display" tab of the specific content type's administration page (Administer > Structure > Content types and the link field display for your content type).

Managing file locations and access

When you create a file field, you can specify the sub-directory of the site's file system where uploaded files for this content type will be stored. The site's file system paths are defined on the File system page (Administer > Configuration > Media: File system).

You can also specify whether files are stored in a public directory or in a private file storage area. Files in the public directory can be accessed directly through the web server; when public files are listed, direct links to the files are used and anyone who knows a file's URL can download the file. Files in the private directory are not accessible directly through the web server; when private files are listed, the links are Drupal path requests. This adds to server load and download time, since Drupal must resolve the path for each file download request, but allows for access restrictions.

The best practice for public files is to store them in the multi-site directory like:

sites/default/files

The default way to securely add a private directory for your files is to use a directory that can not be accessed directly by your web server, but can be accessed by Drupal. Ideally this directory should be located outside of your Drupal root folder.

The simple way to add a private directory for your files is to create a sub-directory under the public directory like:

sites/default/files/private

When you specify the private directory in admin/config/media/file-system it will automatically create the sub-directory & create a simple .htaccess file with Deny from all. This stops Apache from serving files from this directory. Make sure that you test this by adding a file to that directory and verifying that you can't browse there directly. If this isn't working, all files in this directory will be accessible to anyone who can guess the URL! Note that non-Apache web servers may need additional configuration to secure private file directories.

Whenever possible it's recommended that you choose a directory located outside of your Drupal root folder (or actually outside your web root), which may be tricky if you are on a shared host. If you do have access though, you can choose a private directory which will be on the same level as your web root directory (often called public_html or www or similar) using:

../private

Note: The “Default download method” has to be changed to private at admin/config/media/file-system. This will make Drupal apply checks to files.

Accessing Private Files

Once configured, files stored in the private directory are inaccessible via a direct link; however, if Drupal constructs a link to the file, the file will be accessible to anyone who can see the link.

For example: you have created a new content type with a file field which stores files in your site's private file directory. Next you create a node from this new content type and attach two new files. When the node is published links to both attached files are visible and anyone who can view the node may download the files. Now, if you unpublish the node, all attached files become inaccessible for download even if you use the direct link to the files that worked when the node was published.

Re-publish the node, and disable the "display" checkbox for one of the files. Save the node. Now one file is accessible for public download and the other is not accessible--even if you have the direct URL for the file that is not listed you will not be able to download this file.

For finer grained control of who can see/download attached files you will need an additional access control module. You may write a module yourself, or use a contributed module such as Content Access.

Technical Details

PHP configuration

For file uploads to work, PHP must be configured properly. The following PHP configuration variables may need to be set or configured, in your PHP php.ini file, .htaccess file, or settings.php files.

  • file_uploads = On must be set to "On"
  • upload_max_filesize = 24M can't be larger than post_max_size
  • max_input_time = 300 small values may cause timeouts for large file uploads
  • memory_limit = 64M small values may cause out of memory errors for large file uploads
  • max_execution_time = 180 small values may cause timeouts for large file uploads
  • post_max_size = 24M limits the size of input submitted to the website (including attached files)

Further Reference

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

jwgreene’s picture

The article above states "Ideally this directory [for private files] should be located outside of your Drupal root folder." However the default method described just below that puts the private directory below the public folder, thus seeming to not match the ideal.

Detailed instructions on how to set up the private directory in the ideal way would be useful.

Jazman’s picture

I agree - the ideal isn't actually explained! How is one supposed to do it? Step-by-minute step please?

Amber Himes Matz’s picture

I think what is meant is, just like with all Drupal personalization, don't put files in the top/main/root Drupal directory, where all the core files live. Make sure you specify that files that are uploaded go somewhere in the 'sites' directory, such as 'sites/default/files' so that when you upgrade Drupal core, you can follow the traditional instructions for upgrading (i.e. backing up your sites directory and not overwriting it with the new Drupal core files), thus avoiding accidentally deleting all the files that were uploaded through your site.

And then for private files, I followed the instructions above as-is and it worked just as described. Drupal 7 creates an .htaccess in the 'private' directory and if you try to type in the URI to a file in that directory, you will get a 403 Forbidden message returned instead of the file. You will only be able to see the file via a node with appropriate permissions.

Hope that helps clarify.

artgig’s picture

From the original article: "The default way to securely add a private directory for your files is to use a directory that can not be accessed directly by your web server, but can be accessed by Drupal. Ideally this directory should be located outside of your Drupal root folder."

On a VPS I normally put the private directory one directory above the web root. On shared hosting, you may not have access to higher directories, which I'm guessing, is why the .htaccess method is also available.

Say you have drupal installed in /home/some_directory/www, then you could put your private directory in /home/some_directory. So your Configuration->File system->Private file system path setting would be /home/some_directory/private. In other words, you want private to be outside of www if possible.

Hope that makes sense.

CamroS’s picture

Drupal 7 creates an .htaccess in the 'private' directory and if you try to type in the URI to a file in that directory, you will get a 403 Forbidden message returned instead of the file. You will only be able to see the file via a node with appropriate permissions.

Could you please describe in detail which permissions are needed?

My situation:
I am able to upload images (as administrator) to the private folder and to attach one to a page, but it won't be displayed on the page.
The files show up in the content media tab, but when trying to display the media (by double-clicking on the filename) only the tabs "View", "Edit", "Delete" and the filename are shown. The image is not visible!

This problem seems to be related to Media declared private no longer visible: Site broken. Do you have any suggestions?

Kind regards.

authentictech’s picture

Putting files in the root Drupal directory is indeed not recommended; however, the article says it is not recommended to put private files in any directory under the web server root directory (often named www or public_html).

This is because, even though the .htaccess file can restrict access (such as in the given examples), this file can be accidentally deleted or corrupted by the user or technical fault and, thus, the files that were once private become public!

The ideal solution is to use a private directory above the web server root where the web server itself does not allow any public Web access but the software running on the server is able to access it. Some web hosts will allow this and some won't.

stevecory’s picture

Using Drupal version 7.10 a new_content_type was added. New fields were added.
The Field Types and Widgets were set to "File" with "Public - accessible to all site users" access.
The uploaded files reside in a Private file directory /var/www/files.
The Access Control module was added, and the "role based access control settings" has checks in
"View any content" for the "anonymous user". Under the Organic groups global permissions,
the setting for View the new field for existing groups has been selected.
Links to the uploaded files appear, however, when the anonymous user selects the link to
download the file the following error appears:

Notice: Undefined index: field_name in og_field_access_field_access() (line 60 of
/var/www/html/sitename/sites/all/modules/og/og_field_access/og_field_access.module).

And the page shows:

Access Denied
You are not authorized to access this page.

Returning back to the pages added with the content type, then removing the uploaded
files allows the administrator to Manage fields in the content type and make it so
the Upload destination is Public files. The files can then be uploaded once more
and they are accessible by the anonymous user.

Steven Cory
Applications Analyst
Collaborative Studies Coordinating Center
Department of Biostatistics
The University of North Carolina at Chapel Hill

smzakaria’s picture

Hello all,

i am using drupal 7.
1. i need develop a page where the user can see the list of previously uploaded files.
2. and he can also share these files with other users.
3. the list of files will also display there status(shared/not shared)

can anyone guide me how to do this. i would like to develop a module for that. is it possible... will appreciate very if anyone answers on this

rajmataj’s picture

You may want to look into IMCE or at least continue the conversation there as there may already be a module to do what you're looking for.

jalane81’s picture

I can't seem to remove any files or folders that got created during Token/URL testing while setting up a new content type.

I have logged in with a system admin and applied 777 permissions and still cannot delete.

What am I doing wrong? What is the right method to remove old folders/files?

Vlad Stratulat’s picture

Try to check if the owner of those folders is your user with whom you are trying to remove them. If the owner 'www-data', then you can change the owner of this folders to your user. If you cannot, try to user rmdir($dirname) function from your php file on your site. If you have files inside this folder, first you have to remove all files from inside.

snoopy77’s picture

Hi all,
I have a content type with a file field, set up with Upload destination = Private files.
My Private file system path = sites/default/files/private
An authorized user can create a node, and pick and upload a file.
Before saving the node, if he choses to "preview" the node, clicking on the attached file brings it up ok.
So far, so good.
However, once saved out, clicking on the attached file now results in the nasty: Access denied. You are not authorized to access this page".
User 1 (admin) can see fine, though.
Anyone has any idea about what could be wrong ?
Many thanks !

jackhutton’s picture

snoopy77 I would go over to my users and look at anonymous persmissions first.

''The secret though is just keep walking through life without analyzing it too much or clinging to it too much. Just walk on.'' - Marilyn Silverstone, Magnum Photographer & Buddhist Nun, b. March 9, 1929, October 1999.

graper’s picture

I have discovered that even if the Drupal default file system settings is set to Public, you can set the File Field in a content type to Private so long as your Drupal settings have a private folder.

However, there is some issue with the core file field in Drupal 7 in that if the default Drupal file system is set to private and the file field in a content type is set to private, you will get the Access Denied message and 403 error. If you change Drupal config back to public, the file field is still private and will only pull the file from the private area.

I turned in a bug report, but easy enough to work around as the file field can be set to private and works with the private folder even if Drupal's default is public.

Granville

Granville

paulh’s picture


Accessing Private Files


...Re-publish the node, and disable the "display" checkbox for one of the files. Save the node. Now one file is accessible for public download and the other is not accessible--even if you have the direct URL for the file that is not listed you will not be able to download this file.

I don't believe this is correct. If "display" is unchecked, the link to the file doesn't appear in the published page. But the file is still accessible if you know the drupal path to it (for anonymous or authenticated users).

jetwodru’s picture

When I UNCHECKED Display for a private file, though not displayed, anyone CAN still DOWNLOAD the non-displayed private file if he/she remembered the previous drupal link, bug of the system or this article ?

DrupalGod’s picture

Has anyone responded to this? This does like a security issue. I created a content type with a file field set to private. I then restricted access to the content types to specific users. So the node is not viewable unless you are one of those users. The files uploaded for the node, private/filename.pdf for instance, cannot be viewed but the Drupal generated file name (/system/files/filename.pdf) can be viewed by anyone.

VM’s picture

Move the private file folder above the public root and set the path in administer -> file system.

AlviSyhrn’s picture

Thanks for the great tutorial!
But how can I upload more than one file on one article? As I follow this tutorial, I only can upload one file.

shamio’s picture

I think this module can help you to upload multiple files at once. Please try this module: http://drupal.org/project/1115362

Doubt is the father of invention.... موبایل گوشی

angel.h’s picture

When defining the file field just add:
'#attributes' => array('multiple' => 'multiple'), like this:
$form[$fieldset_name]['photos']['files'] = array(
'#type' => 'file',
'#title' => t('Upload photos'),
'#name' => 'files[]',
'#attributes' => array('multiple' => 'multiple'),
);

designingsean’s picture

Before I just start guessing, does anyone have any experience putting the private and tmp folders in a non-web-accessible folder when running on IIS 7? Converting Windows paths to something a *nix-based system can understand seems to be different from project to project.

parvanova’s picture

Hi,
in D7.12 I have a content type with 2 fields in it - the one is File and the other is Image. Both have the "Upload destination" set to "Private files".
In admin/config/media/file-system I have set "Private file system path" to "sites/default/files/private-files" and in it directory there is .htaccess file with "Deny from all" in it.
Files uploaded from File field are OK - they can be downloaded only from users with permissions for that content type.
But the files uploaded from Image field are seen from anyone via path system/files/styles/image_style_name/private/image_name.jpg. The url system/files/image_name.jpg brings the Access denied page.

What should I do to protect image files?
Thanks

vregouby’s picture

subscribe

Progressing web site: http://www.bellitasty.com

atlasc1’s picture

When viewing a node with a file field that contains potentially unlimited files, is there some way to check off particular files and download them as an archive (zip, tar, etc.)? This seems like pretty basic functionality, but I don't see an option or module for accomplishing this.

BernieCram’s picture

A reply to an old question I know, but for future reference have a look at http://drupal.org/project/zipcart

dr-up-all’s picture

I get an "Access denied" error for all users (with permissions) when trying to see uploaded (private) files and this error:
Warning: Cannot modify header information - headers already sent by (output started at /home/***/www/includes/common.inc:2607) en drupal_send_headers() (línea 1243 de /home/***/www/includes/bootstrap.inc).

Can someone help?

marty.true’s picture

I have switched to using a private filesystem and even have the folder completely outside of the public_html folder (up one level) and Drupal creates a symlink to the files and makes a path of http://domain.com/system/files/folder/file.xxx and if you copy paste that from the source code (even anonymous users) can easliy download the file.

So my question is: what is the purpose of having a private filesystem if it is not private at all?
Second question is: How then, DO you protect files from being copied from source code and downloaded?

Gaelan’s picture

Make sure the node containing the file can't be viewed by anonymous users.

Anatsim’s picture

Thanks, it works !

But how to allow view node for anonymous users in order to view available fot download files and index them by Google, but block access to download them ( i.e. error 403 for non-authenticated user if they try to download files ) ?

Slovak’s picture

For anyone struggling... the files will be private ONLY if the node they are associated with is NOT accessible to anonymous users. Even if you store the file as private, if the node is accessible to everyone, everyone can also download from sites/default/files/private

There are a number of modules that manage content permissions, or you can use the built-in taxonomy.

Anatsim’s picture

No, private files stored under alias SYSTEM ( system/files/folder/file.xxx )
They are NOT accessible to anonymous users even if user knows correct real path since this folder is protected by .htaccess.
System could also placed outside web-accessible area to ensure best possible protection.
But you shall define private folder under /admin/config/media/file-system (it is not activated by default)

drupleg’s picture

Slovak thank you for the info! I found this to be exactly my problem, which has been kicking my butt for a while now. Finally I sat down today determined to figure it out and, after 2 hours of Google + trial + error, I found your post which resolved my issue!

My use case is on Drupal 7.14 multisite - I have a node where the body is readable by anonymous, but the PDF file is a private "members only" download. So - anyone can read the teaser, but only members can download the PDF. I thought I could make the file field private, while the body field was public, but this was not the case as anonymous users could still download the file!?

In short - even if a file field is set to a private directory - if anonymous users have permissions to "View Published Content" for that content type, that private file WILL be downloadable to the anonymous user role. Basically the file permission is inherited from the content type/node. If the content type itself is only viewable by an authenticated user, then file access will be denied to anonymous. If the content type is viewable by anonymous, all fields will be accessible by anonymous.

Try it - create a node with a private file; pdf, jpg, etc. Then publish that node so that anonymous can VIEW the node. Now anonymous can also download that private file, even/also by pasting in the "system/private/whatever.pdf" path.

Now go to the permissions page and uncheck "View Published Content" for anonymous users, then copy/paste your private file URL in the address bar - tada = access denied!

This lovely module made Drupal behave the way I expected - by making all private files private so that the body field is public, but the file field on the same node is now private/protected!

http://drupal.org/project/private_files_download_permission

Thanks!
--Tony

rwilson0429’s picture

The field permissions module (http://drupal.org/project/field_permissions) allows you to set permissions on any field, not just private files. So, you could, for example, set your node text and image fields to be viewable by anyone (anonymous) and set the file field attached to the node to be viewable by only authenticated users for example.

ReggieW

ñull’s picture

It is a great idea, but I would like to know if this is just one of the many unproven theories. Is this in fact working in reality? I have seen so many modules that just don't respect the private file system.

An advice for all here. To understand the private file system, first start experimenting with a clean copy of Drupal and with only core modules and use plain role based protection to test it. This will exclude the influence of incompatible modules and takes away their confusion. When you have it working in core, then try adding related modules to see if it continues working like you want it and file bug reports if you find modules that are not respecting the core behaviour. There are many developers out there that never test their modules with the private file system simply because the never use it.

artatum’s picture

@drupleg
Thanks sir.
You saved my life. It took me several days and couldnt achieve it. We had to subscribe to longtail video CDN ! And it was only because I was testing video matters without installing content access BEFORE.
Thanks for your second mail especially (this one) : I couldnt believe the first time you said it! (as others here)...(strange isnt it ?)
But at the second I saw the light. It took me one minute to check it out live.
It will also save us a bunch of €€
Thanks again.

RajabNatshah’s picture

About Having a bundle of Files. as file with unlimited number of files.
the [node:field_file] returns "URL, URL , URL"
How to have this as a list of values.

Rajab Natshah
rajab.natshah.com

szantol’s picture

hi!
try it:
https://drupal.org/project/multiupload_filefield_widget
it allow to upload bulk files

SZL

ñull’s picture

In Drupal 6, to allow caching, I had the private file system enabled on a per folder basis by using .htaccess files with Apache rewrites, disabling rewrites in the folders where cache files were stored.

Here are the steps I needed to migrate the same system to Drupal 7.

ian_m’s picture

I use this field type to allow visitors to download PDF files. However with PDF integration in Chrome (and possibly other browsers) instead of acting as a download the PDF is displayed in the active window. This is not what I want to happen, it would be far better if a new tab was opened for the PDF which would be an option if the download was a conventional link.

Is there a workaround to this?

kerolar’s picture

Did you find a solution to this problem?

Innerform Limited
391 Manchester Road
Heaton Chapel
Stockport
Cheshire
SK4 5BY
United Kingdom
Tel: +44 161 432 4040
www.innerform.com

nfriend’s picture

I use the external module to have PDFs open in another Tab.

https://www.drupal.org/project/external.

It looks like it will forever be in DEV mode but it works. You need to check the PDFs option in its setup to have it work with PDFs.

Neil

reign85’s picture

You can also just change the permission of your directory to make it private.
Personnaly i just apply 711 access to my /sites/all/files/myprivatedirectory

nielsvoo’s picture

Ok, i implemented it but i get access denied on all files, by reading this topic i saw the access code is based on node's but my upload field is attached to a fieldable flag, what can i do to make my files visible for the right users?

thanks...

SomebodySysop’s picture

Running Drupal 7. I have two file fields set up: One is public, the other private. I need to be able to take a file which has been saved as a public file, and switch it to the private file field. And, vice-versa. Can someone provide some some advice on this? Thanks!

webdone’s picture

Hello all,

I use a template with blog pages content type (that includes file field off course).

When I upload an image the file is stored in the directory by default sites/default/files

When the page is displayed the file is accessed in the directory by default sites/default/files/styles/blog_post/public and then the image is not found.

If I add 'styles/blog_post/public' in the 'file directory' field of the 'managed fields' the file is uploaded in the right directory 'sites/default/files/styles/blog_post/public', but now the file displayed is accessed in 'sites/default/files/styles/blog_post/public/styles/blog_post/public'

Then where is defined the default location of the displayed files?

Regards

ArchangelGuidz’s picture

Would there also be a way to delete the files in bulk without doing it one by one in the node edit screen? For now, clicking on "Remove" would do it, but a user would have to wait until the AJAX action is complete before another file can be deleted. Thanks!

nfriend’s picture

Is it possible to have the file module not have to upload a file. We have a bunch of fairly large MP3 files on the server from an older system and would like to have them referenced by a new content type.

We'd like to just copy them to the Files folder and link to them from there.

Any suggestions?

Thanks.

Neil

anrikun’s picture

File Resumable Upload aka file_resup adds large files multiple and resumable upload to the File and Image field widgets.
https://www.drupal.org/project/file_resup

erg-web’s picture

I have set the private folder outside of the root to C:\inetpub\wwwroot\secure and set that ok in the Drupal private files path.

Problem is the CMS editors need to be able to upload files and add to the secure page using CKEditor and the IMCE plugin.

When adding links and browsing server with IMCE this only shows folders from website root downwards and cant access anything above that. So IMCE cant browse the private folder if moved outside root

The idea is its a secure area of the website where editors can upload files to a basic page (secured by node access) then authenticated users can login and see this page and open the PDFs linked from it.

thehuffman’s picture

Just some quick clarification that hopefully will help others who have users uploading files via IMCE in a body text field through CKEditor, or other WYSIWYG tools, and want to make those files "private."

You'll need to instead add a field to your content type that will serve as the place where private files are uploaded.

What I found works best is to:

1. Install the field permissions module (https://www.drupal.org/project/field_permissions)
2. Add a file field to your content type, and set the upload destination to be private
(Note: make sure you've first set up a location for private files under admin/config/media/file-system)
3. In the "Field visibility and permissions" options for your file field select the "custom permissions" option, and set the field to only be viewable to Authenticated Users (i.e., the "view anyone's value..." option in the permission table for the field.)
4. Train your users to use the file field upload option and NOT link from files within the body field if they want them to be private.

Now when you create a new node of your content type, and upload files via the file field you've added, those files will only be viewable to authenticated users, and if one were to try to access the file via the path to that field (which will be something like mysite.com/system/files/my-private-file.pdf) they will get an "access denied" page if they're not logged into the site.

Hope that helps save someone stuck in a similar IMCE hell that I was stuck in!

ungeek’s picture

I had pains, too, trying to protect uploaded attachments against unauthorized download. Field permissions works wonders.

After reading your post, I created a new content type (Private page) with a file field (Private attachments) uploading to the private files directory.

My file system entries are :
   public file system path : sites/default/files
   private file system path : sites/default/files/_private_directory_
   [X] Public local files served by the webserver.

This lets the IMCE file browser used by WYSIWYG editors still find links in the public directories.
And, of course, download attempts from agents outside the authenticated and authorized users fail with a 403 - forbidden error message.

Thanks a lot !

-rg-

-rg-