This was the most time consuming aspect for the recent port of my Document module for Drupal 7.
You would be knowing that File system API underwent a complete revamp in Drupal 7 (see this and this link, a very good introduction of the changes and new concepts is available on Randy Fay’s blog). In Drupal 6, handling file uploads was this easy:
{syntaxhighlighter brush: as3;fontsize: 100; first-line: 1; }$file = file_save_upload(‘file_form_field_name’, array(), ‘relative_path_to_files_folder’);
if ($file !== 0) {
//Set the status of the uploaded file.
file_set_status($file, FILE_STATUS_PERMANENT);
}{/syntaxhighlighter}
Drupal 7 has completely overhauled the File API introducing things like stream wrappers and managed/unmanaged apis etc. You would appreciate the architecture behind these changes in D7 once you understand how it works. But till you do so, it might really get onto you to get it working. And this is what happened to me during the D7 port of the Document module.
I made the following mistakes during the path (which you should avoid obviously):
- The first mistake I made was not to pass the stream wrapper’s scheme to the file_save_upload method. In D7 and using managed File API, you need to pass in the stream wrapper’s scheme compulsarily. I originally tried with this:
$file = file_save_upload('document_filepath', array(), 'docs', FILE_EXISTS_RENAME);
Here “docs” is a sub-folder inside the files folder to which I wanted to save the uploaded file to. Because I wanted to save to the public file-system path, I should have used the “public://” scheme as belows:
$file = file_save_upload('document_filepath', array(), 'public://docs'), FILE_EXISTS_RENAME);
- The base path of the file-system you are trying to save the file to should not be passed to the file_save_upload method. Suppose your public file-system’s path is “sites/default/files”. And you want to save the uploaded file to “sites/default/files/docs”. Then this is the call you should make:
$file = file_save_upload('document_filepath', array(), 'public://docs'), FILE_EXISTS_RENAME);
while I originally tried with this (which was wrong):
$file = file_save_upload('document_filepath', array(), 'public://sites/default/files/docs'), FILE_EXISTS_RENAME);
- Finally the uploaded file’s path in the $file object is now represented by:
$file->uri
in Drupal 7 as opposed to:
$file->filepath
in Drupal 6.
So, here’s the complete code from the Document module to handle a file upload and save it to the public file-system path:
{syntaxhighlighter brush: php;fontsize: 100; first-line: 1; }$file = file_save_upload(‘document_filepath’, array(), ‘public://’ . variable_get(‘document_path’, ”), FILE_EXISTS_RENAME);
if ($file) {
$fid = $file->fid;
$doc_url = file_create_url($file->uri);
//Set the status of the uploaded file.
$file->status = FILE_STATUS_PERMANENT;
file_save($file);
}
else {
drupal_set_message(t(‘Please select a document to upload.’), ‘error’);
}{/syntaxhighlighter}
I am unable to upload zif files…when I try to upload ,a wraning “The specified file sample.zip could not be uploaded. Only files with the following extensions are allowed: jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp.” is shown…
Kindly give me a solution …I tried configuring manage fields etc..but nothing worked..
I have no words to express my gratitude for such a helpful post.
Thanks,
Mudasser
In which file should I change/add this code?
Hi, I’ve read through the post above about not been able to upload a zip, I’m also unable to upload a docx type (and zips).
I looked for the file field on the document content type, but all i see title, body and document types. So I’m unable to change the accepted file types, am I missing something?
Thank
chris
Want to create thumbnail of uploaded images as well as. Anny idea??
Thank u, Can u tell me how drupal’s user module create thumbnail of user’s profile pic??
Thank u so much for your advice. Hv researched a lot and then asked to u. Actly hv asked to a wrong person.
Hi Rahul,
Thank you for the insightful article. I was hoping you could help me with a question:
I am trying to find out how to rename an image filename upon upload. I am using file_save_upload() and I am able to control the filename in the {file_managed} database table with this:
$file->filename = ‘avatar’ . ‘-‘ . $user->uid . ‘-‘ . REQUEST_TIME . ‘.’ . $info[‘extension’];
However, it does not affect the filenames of the image files themselves (that end up in my designated folder directory):
\sites\default\files\avatar_selection
I was hoping you can help me understand how to automatically rename an image filename upon upload. Here is a link to the function code snippet I am working with just in case it is helpful: http://pastebin.com/kwRfUPuQ
Many thnx for your time and consideration.
All the best,
Ben
HI, Thanks to share this.
Hi Rahul,
I am new to Drupal. Using Drupal 7. I am simply trying to create a form that allows users to upload a file to me from a particular page. I have your module installed but am not sure how I can accomplish this. Please help.
Hi Rahul,
Ok. So can I put something on a page that allows an anonymouse user to upload a file to me? This is my goal. Is my best bet to just use PHP on the particular page I need this on? Thanks
Hi,
I came across your site when desperately googling for my problem. It seems that you know a little bit the upload function of Drupal 7, so maybe you have an idea how to solve my problem.
I defined the server path for uploaded files with a token that represents the menu name. So every file is saved in a folder structure which represents the menu structure. But when one day the menu names are changed, it will be too chaotic. So it would be much better to be able to define the server upload path during every file upload. Do you know if there is a module to extend the core upload module for this?
Thanks,
Johny
Hello sir, I have problem with limiting an image or icon file size, the file_validate_size() does’nt work for me. any alternative codes.. Thanks.. I’m new to drupal and looking forward to learn more.. ๐
$form [‘profile’][‘picture’] = array(
‘#type’ => ‘file’,
‘#title’ => t(‘Upload picture’),
‘#maxlength’ => 255,
‘#size’ => 20,
‘#required’ => TRUE,
‘#prefix’ => ‘<div id=”profile-wrapper”>’,
‘#suffix’ => ‘</div>’,
);
$form[‘profile’][‘upload’] = array(
‘#type’ => ‘submit’,
‘#value’ => t(‘upload’),
‘#submit’ => array(‘ajax_profile_upload’),
‘#ajax’ => array(
‘callback’ => ‘ajax_profile_callback’,
‘wrapper’ => ‘profile-wrapper’,
‘method’ => ‘replace’,
‘effect’ => ‘fade’,
‘progress’ => array(‘type’ => ‘bar’, ‘message’ => t(‘Please wait…’))
),
);
function ajax_profile_upload($form,&$form_state){
print ‘<pre>’;
print_r($form_state);
//Here i want to know that the all form content filed values .but it’s but i’s not show any vlaue .
i nedd solution .please give me solution asap. thanks
}
I have noticed, that when a streams format uri is used, then the call to file_save cannot calculate the actual filesize, thus setting it to 0.
As seen from the respective code, the uri is used to resolve the file size
$file->filesize = filesize($file->uri);
but for a uri like ‘public://docs’, method always returns zero. Any ideas?
which element type i will have to use for multiple image upload .and how
I want to store images in a specific directory depending upon the content type.
I don’t know whether is it possible or not.
I want to have different directory for each content type and each has sub directories named according to the terms it is placed under. e.g.
When a new content is added the image should be sotred in the specific directory (say term-3 of content-type-1). Editing, creating and deleting should maintain the hierarchy.
Which file should I need to change in order to achieve this functionality?
โโโโcontent-type-1
โ โโโโterm-1
โ โโโโterm-2
โ โโโโterm-3
โโโโcontent-type-2
โ โโโโterm-1
โ โโโโterm-2
โ โโโโterm-3
โโโโcotent-type-3
โโโโterm-1
โโโโterm-2
โโโโterm-3
Hi ,
What I want to do is , to add a file upload field in theme-settings.php. and I did it .Now the problem is while I upload the image there are two entries in the file_managed table one is with temporary path and one is with public path. And in ppublic path the file name is something like 0.4343423255_434343.jpg while I have uploaded the file with name App_Icon.jpg I want to move the image to public directory with it’s name(App_Icon.jpg) rather name some custom name(0.4343423255_434343.jpg ) . I have altered the theme-settings.php with
themename_form_system_theme_settings_alter(&$form, &$form_state, $form_id = NULL){
$form;
}
After creating the form I have created the validator and submit function for it as below.
function themename_theme_settings_validate($form, &$form_state) {
// Handle file uploads.
$validators = array(‘file_validate_is_image’ => array());
// Check for a new uploaded logo.
$file = file_save_upload(‘custom_image’, $validators);
if (isset($file)) {
// File upload was attempted.
if ($file) {
// Put the temporary file in form_values so we can save it on submit.
$form_state[‘values’][‘custom_image’] = $file;
}
else {
// File upload failed.
form_set_error(‘custom_image’, t(‘The logo could not be uploaded.’));
}
}
}
/**
* Process system_theme_settings form submissions, handling extra values
*/
function themename_theme_settings_submit($form, &$form_state) {
$settings = array();
$values = $form_state[‘values’];
$form_state[‘values’][‘custom_image_path’] = “public://”.$form_state[‘values’][‘custom_image_path’];
// Check for a new uploaded file, and use that if available.
if ($file = file_save_upload(‘custom_image’)) {
$parts = pathinfo($file->filename);
$destination = ‘public://’ . $parts[‘basename’];
$file->status = FILE_STATUS_PERMANENT;
$copyAfter = file_copy($file, $destination, FILE_EXISTS_REPLACE);
if ($copyAfter) {
$_POST[‘custom_image_path’] = $form_state[‘values’][‘custom_image_path’] = $copyAfter->uri;
}
}
cache_clear_all();
}
Now please suggest me, how to make one entry(public) for image upload in file_managed tables rather than making two entries (temporary and public). And how can I save image in public directory with it’s original name.
Thanks
Amit Sharma
hi Rahul,
I am trying to upload a file in drupal7 using my custom form module.I have been working on this for past 2 days, still I am not able to upload a file.so I used your code but still I am not able to upload the file.
$c=$form_state[‘values’][‘upload’];//form field name
$file = file_save_upload($c, array(‘csv’), ‘public://’, FILE_EXISTS_RENAME);
if ($file) {
$fid = $file->fid;
$doc_url = file_create_url($file->uri);
//Set the status of the uploaded file.
$file->status = FILE_STATUS_PERMANENT;
file_save($file);
}
else {
drupal_set_message(t(‘Please select a document to upload.’), ‘error’);
}
please help me out!!
the uploaded image saved in the following folder
/var/www/drupal/sites/default/files/
Following is the code .
copy and paste this code in your custom module file.
$form[‘image_upload’] = array(
‘#type’ => ‘managed_file’,
‘#name’ => ‘custom_image’,
‘#title’ => t(‘Upload your image:’),
‘#size’ => 40,
‘#description’ => t(“Image should be less than 400 pixels wide and in JPG format.”),
‘#upload_location’ => ‘public://files’// the file save in above given location.
);
Hi Rahul!!
Thanks for spending time to share your knowledge. File upload is tricky task and i have been spending one week to finding a solution. Finally i’ve found your post. Thnaks..
Please explain me how to do you read file name from the form??
What are document_filepath and document_path ??
I’ve added a file upload field to my content type. When I try to upload a file using the field I get the following message:
An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (8 MB) that this server supports.
I’ve gone into php.ini by going to the WAMP icon > PHP > php.ini and changed to this:
post_max_filesize = 24MB then it works .My question is that why the file upload button is disappeard. can any one explaine it why this is happing.
I have spent quite a time to solve this issue and finally i got solution in your post.
So thanks a ton and keep the good work on.