I'm using the following CodeIgniter function to upload files which works fine:
function uploadFiles(){
$this->load->library('upload');
$error = 0;
$projectName = $_POST['projectname'];
$projectID = $_POST['maxid'];
$folderName = $this->config->item('upload_dest')."/".$projectName."_".$projectID;
if(!file_exists ($folderName)){
$aa = mkdir($folderName);
}
$config['upload_path'] = $folderName;
$config['allowed_types'] = 'xml';
//$config['allowed_types'] = '*';
$config['max_size'] = '0';
$config['overwrite'] = TRUE;
$this->upload->initialize($config);
for($i=0; $i<count($_FILES['files']['name']); $i++)
{
$_FILES['userfile']['name'] = $_FILES['files']['name'][$i];
$_FILES['userfile']['type'] = $_FILES['files']['type'][$i];
$_FILES['userfile']['tmp_name'] = $_FILES['files']['tmp_name'][$i];
$_FILES['userfile']['error'] = $_FILES['files']['error'][$i];
$_FILES['userfile']['size'] = $_FILES['files']['size'][$i];
if($this->upload->do_upload())
{
$error += 0;
}else{
$error += 1;
}
}
if($error > 0){
$this->upload->display_errors();
return FALSE;
}
else{
return TRUE;
}
}
What I need to do is - check to make sure that at least one of the files which are being uploaded is named "etl". If there's no such a file in the file list the user chosen - stop the action, don't upload anything and return a form validation error. Could anybody advise over this?
Thanks.
Firstly, from php there is no way to get the name of the file(s) before uploading, you must upload to get the properties of the file. So, the options available are:
(1) Allow the files to be uploaded, then get the names and check if any contains "etl". If non contains what you are looking for, then delete the just uploaded files, and set a custom error message yourself.
This approach have a very large overhead cost of allowing you to first upload what is not need, then deleting it. Very poor but solves the problem.
(2) On the otherhand, is the javascript solution. Give the upload fields a common class name
e.g "userfile1", "userfile2", .......
then from your javascript and using jquery, intercept the submission of the form, then use a for loop to get the values of each of the file upload field, from which you can get the full name and extension of the file and then do your "etl" comparison.
i.e
<script type="text/javascript" >
$("#formname").submit(function(){
$(".classname").each(function(){
if($(this).val().indexOf("etl") != -1 ){
return true;
}
});
/*
*whatever makes it finish executing that loop and the execution of code gets
*to this point, then the string "etl" was not found in any of the names.
*/
// write a piece of code to show an hidden error field
$("#hidden_error_div").text("Your error message").show();
return false; //makes sure the form is not submitted.
});
</script>
Hope this helps.
Oyekunmi gives a good javascript solution to intercept before it actually gets to the server. As Oyekunmi points out, once it gets there, it gets there as a package, so you could then store and process it in a temporary directory, eval each file there and process accordingly.
Related
I have a really weird problem. I'm using the CodeIgniter Upload Class for managing the upload of a simple jpg image. If I upload a file with extension .JPG, even if I set the property file_ext_tolower to TRUE, my file gets uploaded with the .JPG extension. Which is something that I don't want! Here is some code..
$this->load->library('upload');
$config['upload_path'] = './resources/img/content';
$config['allowed_types'] = 'jpg';
$config['overwrite'] = FALSE;
$config['file_ext_tolower'] = TRUE;
$config['remove_spaces'] = TRUE;
$this->upload->initialize($config, true);
if ( ! $this->upload->do_upload('cover')) {
$this->session->set_flashdata('message','Cover: ' . $this->upload->display_errors());
redirect('admin');
break;
} else {
// Whatever
}
Problem is, this doesn't run even on localhost. It always goes ahead and uploads the file with the .JPG. I just cannot understand. I'm using CodeIgniter 3.1.0 on both the server and the localhost. Any thoughts? On the server I've also enabled the fileinfo extension in the php.ini.
Another thing that this brings is that..if I have a file named myfile.JPG and myfile.jpg, CodeIgniter isn't able to see that they're the same file..which is ultimately what would be likely it does if only file_ext_tolower was working properly.
On server, myfile.JPG gets saved as myfile.JPG. I think that, when file_ext_tolower is set to TRUE, it should save as myfile.jpg...and eventually, before doing that, actually search for another file with this name..if file with this name is already on the server, it should follow the overwrite setting: either overwrite it or rename with a progressive number.
I have solution for you :)
Create file: application/libraries/MY_Upload.php
<?php
class MY_Upload extends CI_Upload
{
/**
* Force filename to lowercase
*
* #var string
*/
public $file_name_tolower = FALSE;
function _prep_filename($filename)
{
if ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR ($ext_pos = strrpos($filename, '.')) === FALSE)
{
return $filename;
}
$ext = substr($filename, $ext_pos);
$filename = substr($filename, 0, $ext_pos);
//change ext tolower
$filename = ($this->file_name_tolower)?strtolower($filename):$filename;
//change ext tolower
$ext = ($this->file_ext_tolower)?strtolower($ext):$ext;
return str_replace('.', '_', $filename).$ext;
}
}
I modyfication file_ext_tolower and add file_name_tolower
Example for file: coVEr.JPG
...
$config['file_ext_tolower'] = TRUE;
$config['file_name_tolower'] = TRUE;
...
Result: cover.jpg
...
$config['file_ext_tolower'] = TRUE;
$config['file_name_tolower'] = FALSE;
...
Result: coVEr.jpg
...
$config['file_ext_tolower'] = FALSE;
$config['file_name_tolower'] = TRUE;
...
Result: cover.JPG
...
$config['file_ext_tolower'] = FALSE;
$config['file_name_tolower'] = FALSE;
...
Result: coVEr.JPG
I have the same problem. It is silly mistake, no matter how much code i edit on this file also no effect on result. So I start guess I refer to wrong file :
maybe member-site file but I edit admin-site file.
maybe order-model file but I edit invoice-model file.
After echo "alert("abc");" to find the correct file, then i edit the code then finally I get the result output perfectly.
how can I check that user has selected at-least one file for upload in below code ?
i have tried with in_array, isset, !empty functions but no success
please note that userfile input is array in html
if(!empty($_FILES['userfile']['tmp_name'])){
$upload_dir = strtolower(trim($_POST['name']));
// Create directory if it does not exist
if(!is_dir("../photoes/". $upload_dir ."/")) {
mkdir("../photoes/". $upload_dir ."/");
}
$dirname = "../photoes/".$upload_dir;
for($i=0; $i < count($_FILES['userfile']['tmp_name']);$i++)
{
// check if there is a file in the array
if(!is_uploaded_file($_FILES['userfile']['tmp_name'][$i]))
{
$messages[] = 'No file selected for no. '.$i.'field';
}
/*** check if the file is less then the max php.ini size ***/
if($_FILES['userfile']['size'][$i] > $upload_max)
{
$messages[] = "File size exceeds $upload_max php.ini limit";
}
// check the file is less than the maximum file size
elseif($_FILES['userfile']['size'][$i] > $max_file_size)
{
$messages[] = "File size exceeds $max_file_size limit";
}
else
{
// copy the file to the specified dir
if(#copy($_FILES['userfile']['tmp_name'][$i],$dirname.'/'.$_FILES['userfile']['name'][$i]))
{
/*** give praise and thanks to the php gods ***/
$messages[] = $_FILES['userfile']['name'][$i].' uploaded';
}
}
}
}else{
$messages[] = 'No file selected for upload, Please select atleast one file for upload';
dispform();
}
Here's how I do it its a couple of if's and I use a for loop as I allow multiple file uploads from a single drop down but its the if's that are more important to you
$uploaded = count($_FILES['userfile']['name']);
for ($i=0;$i<$uploaded;$i++) {
if (strlen($_FILES['userfile']['name'][$i])>1) {
// file exists so do something
} else {
//file doesn't exist so do nothing
}
}
You'll note I compare against the name element of the global $_FILES this is because you should never be able to upload a file without a name which also applies for no file uploaded
Don't do it client side thats a dumb place to do validation as the user can simply turn js processing off in the browser or it can be blocked by certain addons etc or intercepted and altered via firebug and various browser search hijacking toolbars etc.
Anything like this should always be done server side!
finally I found the answer, I am giving it here for other users,
I have 5 keys in html input array so array index is up to 4
if(!empty($_FILES['userfile']['tmp_name'][0]) or !empty($_FILES['userfile']['tmp_name'][1]) or !empty($_FILES['userfile']['tmp_name'][2]) or !empty($_FILES['userfile']['tmp_name'][3]) or !empty($_FILES['userfile']['tmp_name'][4])){
//at-least one file is selected so proceed to upload
}else{
//no file selected, notify user
}
There are several methods of doing this with PHP (e.g. Check if specific input file is empty), but with JS it's faster and less expensive on the server. Using jQuery you can do this:
$.fn.checkFileInput = function() {
return ($(this).val()) ? true : false;
}
if ($('input[type="file"]').checkFileInput()) {
alert('yay');
}
else {
alert('gtfo!');
}
I am having a spot of trouble with Codeigniter and getting files to rename within the upload process from the Upload Library it has to offer. Now before anyone says it, I am not looking for "encrypted" file names.
My Problem is in uploading images you have a good handful of types you could be dealing with. So how does one change the file name using the file_name config option to a specific schema (which I already have the schema part up and working). But maintain the same file type?
Right now I am attempting
$upload_config['file_name'] = $generated_filename_from_schema
Only problem is $generated_filename_from_schema doesnt have a file extension, and leaving the file extension out of the equation CI seems to ignore it altogether and just takes the file and append_1, _2, _3 as it goes up if the files have the same name, otherwise it just leaves the name intact.
Now I have to pass the $config to CI so it will upload the file, but how can I determin what kind of file I am working with before it trys to upload so I can use my name generation schema.
*edit*
$upload_config['upload_path'] = realpath(APPPATH.'../images/');
$upload_config['allowed_types'] = 'gif|jpg|png';
$upload_config['max_size'] = 0;
$upload_config['max_width'] = 0;
$upload_config['max_height'] = 0;
$upload_config['remove_spaces'] = true;
$upload_config['file_name'] = $this->genfunc->genFileName($uid);
if($this->input->post('uploads'))
{
$this->load->library('upload');
$this->upload->initialize($upload_config);
if (!$this->upload->do_upload())
{
//echo 'error';
echo $config['upload_path'];
$this->data['errors'] = $this->upload->display_errors();
}
else
{
//echo 'uploaded';
$this->data['upload_data'] = $this->upload->data();
}
}
You can use $_FILES array to get original name of file.
Extract extension of original file.Then, append to your new file name.
Try as below
$ext = end(explode(".", $_FILES[$input_file_field_name]['name']));
$upload_config['file_name'] = $this->genfunc->genFileName($uid).'.'.$ext;
Personally, I find CodeIgniter's file uploading class to be somewhat cumbersome. If you want a vanilla PHP solution:
function submit_image(){
$f = $_FILES['image'];
$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($f['tmp_name']);
if(in_array($detectedType, $allowedTypes)){
$pi = pathinfo($f['name']);
$ext = $pi['extension'];
$target = $this->genfunc->genFileName($uid) "." . $ext;
if(move_uploaded_file($f['tmp_name'], $target)){
/*success*/
}
else {/*couldn't save the file (perhaps permission error?*/}
}
else {/*invalid file type*/}
}
I have a form which has 5 file input fields, all works fine with my CRUD methods if the file field is not empty, however the client now wants to set some of the fields to be non mandatory.
This is how I am trying to do it in my code, the problem I am encountering is declaring a null variable(to insert a blank value in the respective database field) if the file field is empty. I get an undefined variable message from codeigniter when nothing is uploaded...
This is the code that code checks if a file has been uploaded or not.
if(isset($_FILES['ticketing_summary_file']))
{
$this->upload->initialize($config);
if($this->upload->do_upload('ticketing_summary_file'))
{
$upload_data=$this->upload->data();
$ticketing_summary_file_name=$upload_data['file_name'];
$ticketing_summary_full_file_path = $path_to_uploads.'/'.$ticketing_summary_file_name;
$show['ticketing_summary_file_url'] = $ticketing_summary_full_file_path;
}
}
if(!isset($_FILES['ticketing_summary_file']))
{
$show['ticketing_summary_file_url'] = $empty_file_message;
}
Then this is how I insert the data into my database... I have tried declaring the contents of 'ticketing_summary_file' in the code below and above, but it says its empty either way
$show = array('tour_id' =>$tour,
'date' => $this->input->post('date'),
'location' => $location);
$id = $this->show_model->save($show);
Cheers for any help,
Dan
I ran into a similar problem. I ended up checking to see if the upload error matched the text in the lang file. There is probably a better way but it was a quick fix for me. I hope it helps.
<?php
//play code file field
$play_code_errors= '';
$data['play_code_file_name'] = uniqid('pc_', true) . 'csv';
$config['upload_path'] = './media/tmp/';
$config['allowed_types'] = 'csv';
$config['max_size'] = '4024';
$config['file_name'] = $data['play_code_file_name'];
$this->upload->initialize($config);
if ( ! $this->upload->do_upload('play_code_file'))
{
$play_code_errors = $this->upload->display_errors();
if($play_code_errors = $this->lang->line('upload_no_file_selected'))
{
$play_code_errors = '';
}
}
on a page, i have :
if (!empty($_FILES['logo']['name'])) {
$dossier = 'upload/';
$fichier = basename($_FILES['logo']['name']);
$taille_maxi = 100000;
$taille = filesize($_FILES['logo']['tmp_name']);
$extensions = array('.png', '.jpg', '.jpeg');
$extension = strrchr($_FILES['logo']['name'], '.');
if(!in_array($extension, $extensions)) {
$erreur = 'ERROR you must upload the right type';
}
if($taille>$taille_maxi) {
$erreur = 'too heavy';
}
if(!empty($erreur)) {
// ...
}
}
The problem is, if the users wants to edit information WITHOUT uploading a LOGO, it raises an error : 'error you must upload the right type'
So, if a user didn't put anything in the inputbox in order to upload it, i don't want to enter in these conditions test.
i tested :
if (!empty($_FILES['logo']['name']) and if (isset($_FILES['logo']['name'])
but both doesn't seems to work.
Any ideas?
edit : maybe i wasn't so clear, i don't want to test if he uploaded a logo, i want to test IF he selected a file to upload, because right now, if he doesn't select a file to upload, php raises an error telling he must upload with the right format.
thanks.
You can check this with:
if (empty($_FILES['logo']['name'])) {
// No file was selected for upload, your (re)action goes here
}
Or you can use a javascript construction that only enables the upload/submit button whenever the upload field has a value other then an empty string ("") to avoid submission of the form with no upload at all.
There is a section in php documentation about file handling. You will find that you can check various errors and one of them is
UPLOAD_ERR_OK
Value: 0; There is no error, the file uploaded with success.
<...>
UPLOAD_ERR_NO_FILE
Value: 4; No file was uploaded.
In your case you need code like
if ($_FILES['logo']['error'] == UPLOAD_ERR_OK) { ... }
or
if ($_FILES['logo']['error'] != UPLOAD_ERR_NO_FILE) { ... }
You should consider checking (and probably providing appropriate response for a user) for other various errors as well.
You should use is_uploaded_file($_FILES['logo']['tmp_name']) to make sure that the file was indeed uploaded through a POST.
I would test if (file_exists($_FILES['logo']['tmp_name'])) and see if it works.
Or, more approperately (thanks Baloo): if (is_uploaded_file($_FILES['logo']['tmp_name']))
We Could Use
For Single file:
if ($_FILES['logo']['name'] == "") {
// No file was selected for upload, your (re)action goes here
}
For Multiple files:
if ($_FILES['logo']['tmp_name'][0] == "") {
// No files were selected for upload, your (re)action goes here
}
if($_FILES["uploadfile"]["name"]=="") {}
this can be used
No file was selected for upload, your (re)action goes here in if body
echo "no file selected";
if ($_FILES['logo']['error'] === 0)
is the only right way