How to upload Image in Mojolicious
Tags: perl, webdev, mojolicious
Published: 2020-04-19 14:28:05

![](https://user-images.githubusercontent.com/12954663/79690232-06801d80-8277-11ea-9318-0b8911fa3627.jpg)

Hello Mojo learners, in this article we learn, how to upload image to the web server using Mojolicious framework.

In every or in most of the web applications, it is required to upload the image to the web server. Be it a user profile image or blog cover image or the home page etc. 

## PreRequisites

Before proceeding, there are some prerequisites:

1. Perl elementary knowledge required.
2. Understanding of Mojolicious
3. Mojolicious

If you are not familiar with anyone of the above, then I recommend to get required elementary knowledge.

We already cover how to install and setup the Moliicous Project [here](https://ashutosh.dev/blog/post/2020/03/how-to-install-mojolicious).

Hold on for a moment, and Let's think about the steps that we need to follow to upload he image:

1. We need to register a route first to open the image upload form.
2. We need to create a Controller to accommodate the above route.
3. Image upload form template.
4. We need to create a Controller to post and save the image to the server.

Go to the MyApp.pm and in the startup subroutine register the route under the the startup subroutine.

```perl
$r->get('/upload_image')->to(
  controller => 'UploadImageController', action     => 'index'
);
```

It says, when a user hits *upload_image* route, it goes to the **UPloadImageController** and looks out for the **index** subroutine. At present, we don't have the **UploadImageController** yet. Create it under the Controller folder.

```perl
package MyApp::Controller::UploadImageController;
use Mojo::Base 'Mojolicious::Controller';

use strict;
use warnings;

# This subroutine is to show the upload_image route.
sub index {
  my $c = shift;

  $c->render( template => 'uploadImage');
}

1;
```

In the subroutine, $c is the default variable and we render the template under the templates folder. We have not created the template yet. Before creating *uploadImage.html.ep* file go to the default.html.ep under the layouts and add bootstrap 4 files in it.

```html
<!DOCTYPE html>
<html>

<head>
    <title>Upload Image</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />

</head>

<body>
    <%= content %>

    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
        crossorigin="anonymous">
    </script>
    
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous">
    </script>
    
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
        crossorigin="anonymous">
    </script>
</body>

</html>
```

Now, create *uploadImage.html.ep* file

```html
% layout 'default';
<br />
<br />

<div class="col-md-6 mx-auto">
    <form method="post" action="/upload_image">
        
      	<div class="input-group">
            
          	<div class="custom-file">
                
              	<input type="file" 
                       class="custom-file-input" 
                       name="upload_image" 
                       id="upload_image" 
                       accept="image/x-png,image/gif,image/jpeg, image/jpg"
                       type='file'
                       required 
                />
            
              	<label class="custom-file-label" for="upload_image">Select Image</label>
            
          	</div>
            
          <div class="input-group-append">
            
            	<input class="btn btn-primary" type="submit" value="Upload" />
        
          </div>
        
      	</div>

  	</form>

</div>
```

Visit the browser *http://localhost:3000/upload_image*

![upload_image](https://user-images.githubusercontent.com/12954663/79683799-0fa6c580-824a-11ea-84eb-2de1c372e10d.jpg)

So far, In the template, we created a form to upload the image. But we have not registered the route to upload the image. 

In the MyApp.pm file, under the startup sub routine, 

```perl
$r->post('/upload_image')->to(
    controller => 'UploadImageController',
    action     => 'upload_image'
);
```

Create an action *upload_image* under UploadImageController

At the starting of the file add two constants

```perl
use constant ROOT      => 'YOUR_PROJECT_PATH';
use constant IMAGE_LOC => 'YOUR_IMAGE_LOC';
```



```perl
# This subroutine is to upload the image to the web app.
sub upload_image {
    my $c = shift;

    my ( $image, $image_file );

    if ( !$c->param('upload_image') ) {
        $c->flash( error => 'Image is required.' );
        $c->redirect_to('/upload_image');
    }

    # Check for Valid Image Extension
    if ( $c->param('upload_image')->filename !~ /\.png$|\.jpg$|\.jpeg$/ ) {
        $c->flash( error => 'Invalid Image Extension.' );
        $c->redirect_to('/upload_image');
    }

		# Upload the image
    $image = $c->req->upload('upload_image');

    $image_file = ROOT . IMAGE_LOC . $c->param('upload_image')->filename;

    $image->move_to($image_file);

    $c->flash( message => 'Image Uploaded successfully.' );
    $c->redirect_to('/upload_image');

}
```

Complete *UploadImageController*, looks like

```perl
package MyApp::Controller::UploadImageController;
use Mojo::Base 'Mojolicious::Controller';

use strict;
use warnings;

use constant ROOT      => 'PROJECT_PATH';
use constant IMAGE_LOC => 'IMAGE_LOC';

sub index {
    my $c = shift;

    $c->stash( error   => $c->flash('error') );
    $c->stash( message => $c->flash('message') );

    $c->render( template => 'uploadImage' );
}

# This subroutine is to upload the image to the web app.
# As far as I concerned it looks good to me.
sub upload_image {
    my $c = shift;

    my ( $image, $image_file );

    if ( !$c->param('upload_image') ) {
        $c->flash( error => 'Image is required.' );
        $c->redirect_to('/upload_image');
    }

    # Check for Valid Image Extension
    if ( $c->param('upload_image')->filename !~ /\.png$|\.jpg$|\.jpeg$/ ) {
        $c->flash( error => 'Invalid Image Extension.' );
        $c->redirect_to('/upload_image');
    }

		# Upoload the image
    $image = $c->req->upload('upload_image');

    $image_file = ROOT . IMAGE_LOC . $c->param('upload_image')->filename;

    $image->move_to($image_file);

    $c->flash( message => 'Image Uploaded sucessfully.' );
    $c->redirect_to('/upload_image');

}

1;
```

Open the uploadimage template and add at the last of the file

```html
<br>
% if ( $error ) {
    <div class="alert alert-danger">
        <p> <%= $error %> </p>
    </div>
% }

% if ( $message ) {
    <div class="alert alert-success col-md-6 mx-auto">
        <p> <%= $message %> </p>
    </div>
% }
```



Your complete html file looks like

```html
% layout 'default';

<br />
<br />

<div class="col-md-6 mx-auto">
    <form method="post" action="/upload_image" enctype ="multipart/form-data">
        <div class="input-group">
            <div class="custom-file">
                <input type="file" 
                       name="upload_image" 
                       id="upload_image" 
                       accept="image/x-png,image/gif,image/jpeg"
                       required
                />
                <label class="custom-file-label" for="upload_image">Select Image</label>
            </div>
            <div class="input-group-append">
                <input class="btn btn-primary" type="submit" value="Upload" />
            </div>
        </div>
    </form>
</div>
<br>
% if ( $error ) {
    <div class="alert alert-danger">
        <p> <%= $error %> </p>
    </div>
% }

% if ( $message ) {
    <div class="alert alert-success col-md-6 mx-auto">
        <p> <%= $message %> </p>
    </div>
% }
```



Now go to the browser, and select the image, and you'll see similar to this.

![](https://user-images.githubusercontent.com/12954663/79689944-91f8af00-8275-11ea-84fc-669a4c496fc9.jpg)

That's all for now. In this article, we see how to upload the image using the Mojolicious framework. This code has one issue, it doesn't check the size of the image uploaded. I'll leave to the readers to figure it out. 

**Hint**: $c->param('upload_image')->size