I have focused here on uploading files in the admin area. The same technique could be applied to the frontend though.

First, here is a code sample to add a field to a form of type file;

<?php

$fieldset->addField(
    'title',
    'file',
    [
        'name' => 'file',
        'label' => __('File label'),
        'required' => true
    ]
);

This will render a html field on your form similar to the following; Note the name=”file”. That is important because we will need to reference that later on in our controller.

You also need to make sure that your form has an enctype of multipart/form-data. You can do this when the form is initialized.

So you have a form with an input type=”file” box. You select the file you want to upload and press “save”.

Now what?

We start with a controller to handle the request. You already know how controllers work in Magento 2, don’t you?

In app/code/[codePool]/[Vendor]/[ModuleName]/Controller/Adminhtml/[ControllerName].php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php

namespace [Vendor]\[ModuleName]\Controller\Adminhtml;

use Magento\Backend\App\Action;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\MediaStorage\Model\File\UploaderFactory;

class [ControllerName] extends Action
{
    protected $fileSystem;

    protected $uploaderFactory;

    protected $allowedExtensions = ['csv'];

    protected $fileId = 'file';

    public function __construct(
        Action\Context $context,
        Filesystem $fileSystem,
        UploaderFactory $uploaderFactory
    ) {
        $this->fileSystem = $fileSystem;
        $this->uploaderFactory = $uploaderFactory;
        parent::__construct($context);
    }

    public function execute()
    {
        $destinationPath = $this->getDestinationPath();

        try {
            $uploader = $this->uploaderFactory->create(['fileId' => $this->fileId])
                ->setAllowCreateFolders(true)
                ->setAllowedExtensions($this->allowedExtensions)
                ->addValidateCallback('validate', $this, 'validateFile');
            if (!$uploader->save($destinationPath)) {
                throw new LocalizedException(
                    __('File cannot be saved to path: $1', $destinationPath)
                );
            }

            // @todo
            // process the uploaded file
        } catch (\Exception $e) {
            $this->messageManager->addError(
                __($e->getMessage())
            );
        }
    }
    
    public function validateFile($filePath)
    {
        // @todo
        // your custom validation code here
    }

    public function getDestinationPath()
    {
        return $this->fileSystem
            ->getDirectoryWrite(DirectoryList::TMP)
            ->getAbsolutePath('/');
    }
}

protected $allowedExtensions = [] really depends on your application. If you are uploading images then this may look like ['jpg', 'gif']

protected $fileId = 'file' is important. This is the name of the input file box we discussed earlier. If you change the name of your input box when outputting the form field, change this too.

The bulk of the work is done by the Magento\Framework\File\Uploader model (Line 37 to 45). It handles upload, validation (maybe some custom validation) and file saving.

If you want to add some custom validation to your file, you can do this quite trivially. I have provided an example above. You basically add a validateCallback('<callbackName>', <callbackObject>, '<callbackFunction>') to the uploader. To fail the validation, you need only to throw an exception from inside your validation function.

There is another good example of validation callback in Magento\Config\Model\Config\Backend\File.php.

Lovely job.

File Uploads in System Configuration

If you are adding a file upload to the system configuration area of Magento, the actual uploading of the file is taken care of for you.

When you add your field though you just need to specify some configuration to give Magento a clue as to where the file should be uploaded;

<field id="file" translate="label comment" type="file" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
    <label>File</label>
    <upload_dir config="config/path">config/path</upload_dir>
</field>

There are lots of other configuration you can add to the field. For example; frontend_type for custom rendering or backend_type to add validation, amongst others.

  • magento2

Like this post? Share it :)


Related Posts

Back