Writing the code to upload images to a server from scratch seems like a very daunting chore. I'm going to brand a very elementary upload grade to demonstrate how file data works and can be transferred.

In this tutorial, we're going to build an upload form with HTML, send the files with JavaScript, and process and upload them with PHP.

Note that this is not meant to exist fully functional, secure, validated, production code. Information technology is just meant to demonstrate in a simple and straightforward style how to make your first upload course.

  • View Source on GitHub

Prerequisites

  • A basic noesis of HTML
  • A bones noesis of PHP syntax and code structure
  • An understanding of local PHP environments. If y'all don't know what that means, please read this guide on how to prepare up a MAMP environment.

Goals

  • Build the simplest possible class with HTML to take a remember files from your local computer.
  • Send the data from an HTML form to a PHP script with vanilla JavaScript.
  • Process the information in the PHP script and move the local files to an uploads/ directory on a server.

Setup

Equally mentioned in the prerequisites, you must accept a basic noesis of PHP and local server environments.

If y'all already know how to apply PHP and local environments, skip to the next department.

If y'all're using a Mac, you can create a server with a single command. To test this, create a file called test.php in the directory of your choice. I'm going to create a directory called local. The total path volition be Users/tania/local.

test.php

                                          <?php                repeat                'This is only a exam.'                ;                                    

In the Terminal application, which I'll open by pressing SPACEBAR + COMMAND and typing Terminal, navigate to the directory you created your file in.

You should at present be able to go to http://localhost:8888/exam.php and see the output of the code.

Screen Shot 2018 04 26 at 3 50 21 PM

If you're on Windows, or y'all don't want to use the command line, ready MAMP.

Building an Upload Grade in HTML

In the root of your local server, create an alphabetize.html file. Nosotros'll simply create a quick skeleton.

                                          <!                DOCTYPE                html                >                                                              <html                lang                                  =                  "en"                                >                                                              <head                >                                                              <meta                charset                                  =                  "UTF-8"                                />                                                              <meta                proper name                                  =                  "viewport"                                content                                  =                  "width=device-width, initial-scale=1.0"                                />                                                              <meta                http-equiv                                  =                  "X-UA-Compatible"                                content                                  =                  "ie=border"                                />                                                              <title                >              Upload Files                                  </championship                >                                                              </head                >                                                              <torso                >                            <!-- course goes here-->                                                </body                >                                                              </html                >                                    

Let'south add together an HTML web form to the body.

                                                            <form                method                                  =                  "post"                                enctype                                  =                  "multipart/form-data"                                >                                                              <input                blazon                                  =                  "file"                                name                                  =                  "files[]"                                multiple                />                                                              <input                type                                  =                  "submit"                                value                                  =                  "Upload File"                                name                                  =                  "submit"                                />                                                              </form                >                                    

In this form, we're using the POST HTTP method, which how we send data. The multipart/form-information value is required for uploading files in forms.

From here, nosotros're creating a file input type that takes an array of files (files[]) and we're specifying multiple to let more than than one file to be selected. files[] tin can accept any name - you could use uploads[] or images[], but I called it files[] for simplicity.

Finally, we take a submit button. Since the side by side step volition be to add a script, let's simply add a link to the JavaScript file we'll create.

                                                            <script                src                                  =                  "upload.js"                                >                                                                            </script                >                                    

And that's all we need for the view.

alphabetize.html

                                          <!                DOCTYPE                html                >                                                              <html                lang                                  =                  "en"                                >                                                              <head                >                                                              <meta                charset                                  =                  "UTF-eight"                                />                                                              <meta                name                                  =                  "viewport"                                content                                  =                  "width=device-width, initial-scale=one.0"                                />                                                              <meta                http-equiv                                  =                  "Ten-UA-Uniform"                                content                                  =                  "ie=edge"                                />                                                              <title                >              Upload Files                                  </title                >                                                              </head                >                                                              <body                >                                                              <form                method                                  =                  "post"                                enctype                                  =                  "multipart/class-information"                                >                                                              <input                type                                  =                  "file"                                name                                  =                  "files[]"                                multiple                />                                                              <input                type                                  =                  "submit"                                value                                  =                  "Upload File"                                name                                  =                  "submit"                                />                                                              </form                >                                                              <script                src                                  =                  "upload.js"                                >                                                                            </script                >                                                              </body                >                                                              </html                >                                    

Screen Shot 2018 04 26 at 4 12 29 PM

Sending Course Data via JavaScript

Correct now, clicking submit on the grade doesn't become anywhere. Since nosotros don't take an activity that leads to a URL, the form will just post to itself by default. Since alphabetize.html is an html file, not a PHP file, no form processing can happen on this page. Instead, we'll ship the form to PHP through JavaScript.

Create a file chosen upload.js.

First, let's define two variables - the URL where nosotros want to send the information, and the DOM element for the class.

upload.js

                          // Ascertain processing URL and form element              const              url              =              'procedure.php'              const              form              =              document.              querySelector              (              'grade'              )                      

We're going to add an event listener to watch for the form being submitted, only we'll forestall the default action from firing.

                          // Listen for form submit              form.              addEventListener              (              'submit'              ,              (              eastward              )              =>              {              e.              preventDefault              (              )              // ...              }              )                      

Let's get together the files with the .files property, and brainstorm a new FormData() interface.

                          // Get together files and begin FormData              const              files              =              document.              querySelector              (              '[type=file]'              )              .files;              const              formData              =              new              FormData              (              )              ;              }              )              ;              // ...                      

For each file that has been submitted, suspend it to the files[] array.

                          // Append files to files assortment              for              (              let              i              =              0              ;              i              <              files.length;              i++              )              {              allow              file              =              files[i]              formData.              append              (              'files[]'              ,              file)              }              // ...                      

Finally, use the congenital-in Fetch API to Mail the data to the URL we specified. Print the response to the console (for testing purposes).

                          fetch              (url,              {              method:              'POST'              ,              body:              formData,              }              )              .              then              (              (              response              )              =>              {              panel.              log              (response)              }              )                      

Hither is the completed upload.js.

upload.js

                          const              url              =              'procedure.php'              const              course              =              document.              querySelector              (              'grade'              )              form.              addEventListener              (              'submit'              ,              (              due east              )              =>              {              e.              preventDefault              (              )              const              files              =              certificate.              querySelector              (              '[type=file]'              )              .files              const              formData              =              new              FormData              (              )              for              (              let              i              =              0              ;              i              <              files.length;              i++              )              {              let              file              =              files[i]              formData.              append              (              'files[]'              ,              file)              }              fetch              (url,              {              method:              'POST'              ,              trunk:              formData,              }              )              .              then              (              (              response              )              =>              {              console.              log              (response)              }              )              }              )                      

Now - how can we test if all this information is going through properly? Let's impress out the file information.

Create a new file called process.php, and print out the contents of the superglobal array $_FILES, which will contain the data for all our files.

process.php

Once you have this file, attempt uploading a few files through the course. I made a phplogo.png and testfile1.txt to test with, and uploaded the file.

In Developer Tools, under the Panel, you should see a response like this:

Developer Tools -> Panel

                                                                                                                                                        Response              {              blazon:              "basic",   url:              "http://localhost:8888/process.php",   redirected: faux,   status:              200,   ok: true, …              }                      

If yous see status: 200, this ways the file hit the proper URL and the URL exists.

At present in Developer tools, click on the Network tab. You should encounter the filename procedure.php. Click on the file, and click on Response. There, you should see the output of print_r($FILES). Information technology volition wait something like this:

Developer Tools -> Network -> Response

                          [files]              =>              Assortment              (              [name]              =>              Array              (              [              0              ]              =>              phplogo.png              [              1              ]              =>              testfile1.txt              )              [blazon]              =>              Assortment              (              [              0              ]              =>              paradigm/png              [              i              ]              =>              text/plain              )              [tmp_name]              =>              Assortment              (              [              0              ]              =>              /              private              /              var              /xxx              [              1              ]              =>              /              private              /              var              /yyy              )              [fault]              =>              Assortment              (              [              0              ]              =>              0              [              one              ]              =>              0              )              [size]              =>              Assortment              (              [              0              ]              =>              16610              [              1              ]              =>              12              )              )                      

At present we know the proper files, along with all their associated data, accept gone through. Success!

Processing Form Data with PHP

Now that nosotros're gathering all the files from the course and sending them to process.php with JavaScript, nosotros have to move the file data with PHP.

Commencement, nosotros'll want to make sure the lawmaking only runs when a Mail request hits the file.

procedure.php

                                          <?php                if                (                $_SERVER                [                'REQUEST_METHOD'                ]                ===                'POST'                )                {                // ...                }                                    

We as well want to make sure files take gone through.

                          if              (              isset              (              $_FILES              [              'files'              ]              )              )              {              // ...              }                      

Create a directory in the root of your projection chosen uploads. This directory volition demand to accept 755 permissions to accept incoming files.

At this signal, we'll create an array for errors, set the path of the directory where uploads should go, and set the approved extensions.

                          $errors              =              [              ]              ;              $path              =              'uploads/'              ;              $extensions              =              [              'jpg'              ,              'jpeg'              ,              'png'              ,              'gif'              ]              ;                      

Since the user can upload multiple files, we'll create an $all_files variable, get the number of files being uploaded, and make a for loop.

                          $all_files              =              count              (              $_FILES              [              'files'              ]              [              'tmp_name'              ]              )              ;              for              (              $i              =              0              ;              $i              <              $all_files              ;              $i              ++              )              {              // ...              }                      

Now, for each file nosotros'll get the file name, temporary file data, type, size, and extension.

                          $file_name              =              $_FILES              [              'files'              ]              [              'name'              ]              [              $i              ]              ;              $file_tmp              =              $_FILES              [              'files'              ]              [              'tmp_name'              ]              [              $i              ]              ;              $file_type              =              $_FILES              [              'files'              ]              [              'type'              ]              [              $i              ]              ;              $file_size              =              $_FILES              [              'files'              ]              [              'size'              ]              [              $i              ]              ;              $file_ext              =              strtolower              (              stop              (              explode              (              '.'              ,              $_FILES              [              'files'              ]              [              'name'              ]              [              $i              ]              )              )              )              ;              $file              =              $path              .              $file_name              ;                      

At present we tin can set a few rules for the files. If the file type in non in the approved list of extensions, or the file is too big, we'll add it to the error array. I set a file size of 2 megabytes.

                          if              (              !              in_array              (              $file_ext              ,              $extensions              )              )              {              $errors              [              ]              =              'Extension not allowed: '              .              $file_name              .              ' '              .              $file_type              ;              }              if              (              $file_size              >              2097152              )              {              $errors              [              ]              =              'File size exceeds limit: '              .              $file_name              .              ' '              .              $file_type              ;              }                      

If there were no errors, we can go alee and motion the file to the uploads folder with the move_uploaded_file command.

                          if              (              empty              (              $errors              )              )              {              move_uploaded_file              (              $file_tmp              ,              $file              )              ;              }                      

At present we can close out the for loop, and print out the errors. This will display for usa in the network tab we used before to see the output of $_FILES.

                          if              (              $errors              )              print_r              (              $errors              )              ;                      

Put it all together, and here's procedure.php.

process.php

                                          <?php                if                (                $_SERVER                [                'REQUEST_METHOD'                ]                ===                'Mail service'                )                {                if                (                isset                (                $_FILES                [                'files'                ]                )                )                {                $errors                =                [                ]                ;                $path                =                'uploads/'                ;                $extensions                =                [                'jpg'                ,                'jpeg'                ,                'png'                ,                'gif'                ]                ;                $all_files                =                count                (                $_FILES                [                'files'                ]                [                'tmp_name'                ]                )                ;                for                (                $i                =                0                ;                $i                <                $all_files                ;                $i                ++                )                {                $file_name                =                $_FILES                [                'files'                ]                [                'name'                ]                [                $i                ]                ;                $file_tmp                =                $_FILES                [                'files'                ]                [                'tmp_name'                ]                [                $i                ]                ;                $file_type                =                $_FILES                [                'files'                ]                [                'type'                ]                [                $i                ]                ;                $file_size                =                $_FILES                [                'files'                ]                [                'size'                ]                [                $i                ]                ;                $file_ext                =                strtolower                (                cease                (                explode                (                '.'                ,                $_FILES                [                'files'                ]                [                'name'                ]                [                $i                ]                )                )                )                ;                $file                =                $path                .                $file_name                ;                if                (                !                in_array                (                $file_ext                ,                $extensions                )                )                {                $errors                [                ]                =                'Extension not allowed: '                .                $file_name                .                ' '                .                $file_type                ;                }                if                (                $file_size                >                2097152                )                {                $errors                [                ]                =                'File size exceeds limit: '                .                $file_name                .                ' '                .                $file_type                ;                }                if                (                empty                (                $errors                )                )                {                move_uploaded_file                (                $file_tmp                ,                $file                )                ;                }                }                if                (                $errors                )                print_r                (                $errors                )                ;                }                }                                    

Now exam it out. If you apply the grade to upload some files, y'all'll see them in the uploads folder. If you try to upload a file that's too large or of the incorrect blazon, you'll see the errors in the Network response.

Conclusion

Congratulations, you've successfully created a functioning upload form. This is an heady niggling process if you've never successfully uploaded a file or used the $_FILES superglobal before.

The complete source is on GitHub.

  • View Source on GitHub

Note that this is non a complete, secure, production process. Hither are a few things to take into consideration:

  • At that place is no JavaScript side validation. The user should be shown an error on the forepart terminate if their file is of the incorrect type earlier they submit.
  • Dealing with mutiple files with the same name.
  • This method of error handling is only for the development process.

Thanks for reading. I can besides brand 1 almost uploading to Amazon S3 and/or DigitalOcean Spaces if there's involvement.