2

I just wanted to know if there is a way to limit the file input dialog to show only certain kinds of files. My web page only can accept .bin or .gz file types, but the user can select other file types and try to upload them.

What would be the best way to prevent the wrong kind of file from being uploaded?

Here is my controller for file uploading:

    public function uploadFile()
    {
        $this->Session->write('isFileUpload', false);
        $this->Session->write('isFileLarge', false);

        if($this->request->is('post'))
        {
            $uploadedFile = array();

            // Check if the Document object is set
            // If it is set, process the file for uploading,
            if(isset($this->request->data['Document']))
            {
                $filename = $this->request->data['Document']['MyFile']['tmp_name'];

                $uploadedFile['MyFile']['name'] = $this->request->data['Document']['MyFile']['name'];
                $uploadedFile['MyFile']['type'] = $this->request->data['Document']['MyFile']['type'];
                $uploadedFile['MyFile']['size'] = $this->request->data['Document']['MyFile']['size'];

                // Move the file to the /home/spectracom folder
                $filePath = DS . 'home' . DS . $uploadedFile['MyFile']['name'];

                if (move_uploaded_file($filename, $filePath))
                {
                    $this->Session->write('isFileUpload', true);
                    $this->Session->write('isFileLarge', false);
                    $this->redirect('/tools/upgradebackup');
                }
                else
                {
                    $this->Session->write('isFileUpload', false);
                    $this->Session->write('isFileLarge', true);
                    $this->redirect('/tools/upgradebackup');
                }
            }
            else
            {
                $this->Session->write('isFileUpload', false);
                $this->Session->write('isFileLarge', true);
                $this->redirect('/tools/upgradebackup');
            }
        }
    }

I basically check that the file exists, or else it is too large, and when it returns to the main upgrade page it sets the session variables.

Thanks

RXC
  • 1,233
  • 5
  • 36
  • 67

2 Answers2

5

You limit what the browser allows the user to select in the file selection dialog using the accept attribute, although not all browsers support it.

I think this should work for creating the input (you'll need to play around with the MIME types to see what works):

echo $this->Form->input('MyFile', array('type' => 'file', 'options' => array('accept' => 'application/gzip,application/gzipped,application/octet-stream')));

You should also validate the files once they arrive on the server by setting up validation on your model (look at extension and mimeType validation rules).

You can also use JavaScript to validate the file extension once it has been selected by the user, and clear the file input field if it has the wrong extension.

Community
  • 1
  • 1
bjudson
  • 4,073
  • 3
  • 29
  • 46
  • I have come across that too. I do validate on the server side, checking for the correct file type. But I would also like to know how to limit it client side. I just want people to be able to only see certain file types. – RXC Aug 28 '12 at 15:38
  • I just updated the answer after doing some quick research. Use the accept attribute where available, and then use JS and model validation. – bjudson Aug 28 '12 at 15:39
  • Thanks for that. Would you know how to incorporate the accept into this? `echo $this->Form->input('MyFile', array('type' => 'file'));` – RXC Aug 28 '12 at 15:50
  • I think list filetypes will be helpful: http://api.cakephp.org/1.3/source-class-MediaView.html#24-83 – Vy Do Dec 18 '14 at 03:08
  • Not working yet. I try above snippet code with CakePHP 2.5.7, but not working. Let's see html source what snippet code rendered. – Vy Do Dec 18 '14 at 04:08
0

Tested with Cakephp 3.4

$this->Form->control('my_file', ['label' => 'Upload File','type' => 'file', 'accept' => 'application/msword']);