Writing the code to upload images to a server from scratch seems like a very daunting task. I'm going to make a very simple upload grade to demonstrate how file information works and can be transferred.

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

Note that this is not meant to be fully functional, secure, validated, product lawmaking. Information technology is simply meant to demonstrate in a simple and straightforward way how to make your starting time upload grade.

  • View Source on GitHub

Prerequisites

  • A bones noesis of HTML
  • A basic knowledge of PHP syntax and lawmaking construction
  • An understanding of local PHP environments. If y'all don't know what that means, delight read this guide on how to fix a MAMP environment.

Goals

  • Build the simplest possible course with HTML to take a retrieve files from your local computer.
  • Transport the data from an HTML course to a PHP script with vanilla JavaScript.
  • Process the data in the PHP script and move the local files to an uploads/ directory on a server.

Setup

Every bit mentioned in the prerequisites, y'all must have a bones noesis of PHP and local server environments.

If you already know how to use PHP and local environments, skip to the adjacent department.

If y'all're using a Mac, you lot tin can create a server with a single command. To exam this, create a file called examination.php in the directory of your choice. I'one thousand going to create a directory called local. The full path volition be Users/tania/local.

test.php

                                          <?php                echo                'This is only a test.'                ;                                    

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

Yous should now be able to get to http://localhost:8888/test.php and see the output of the lawmaking.

Screen Shot 2018 04 26 at 3 50 21 PM

If you're on Windows, or you don't desire to use the command line, set upward MAMP.

Building an Upload Form in HTML

In the root of your local server, create an index.html file. We'll just create a quick skeleton.

                                          <!                DOCTYPE                html                >                                                              <html                lang                                  =                  "en"                                >                                                              <caput                >                                                              <meta                charset                                  =                  "UTF-8"                                />                                                              <meta                name                                  =                  "viewport"                                content                                  =                  "width=device-width, initial-calibration=1.0"                                />                                                              <meta                http-equiv                                  =                  "Ten-UA-Compatible"                                content                                  =                  "ie=edge"                                />                                                              <championship                >              Upload Files                                  </title                >                                                              </head                >                                                              <trunk                >                            <!-- form goes here-->                                                </body                >                                                              </html                >                                    

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

                                                            <class                method                                  =                  "postal service"                                enctype                                  =                  "multipart/form-data"                                >                                                              <input                type                                  =                  "file"                                name                                  =                  "files[]"                                multiple                />                                                              <input                type                                  =                  "submit"                                value                                  =                  "Upload File"                                name                                  =                  "submit"                                />                                                              </grade                >                                    

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

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

Finally, we have a submit button. Since the next footstep will be to add a script, allow's simply add a link to the JavaScript file nosotros'll create.

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

And that'due south all we need for the view.

index.html

                                          <!                DOCTYPE                html                >                                                              <html                lang                                  =                  "en"                                >                                                              <caput                >                                                              <meta                charset                                  =                  "UTF-8"                                />                                                              <meta                name                                  =                  "viewport"                                content                                  =                  "width=device-width, initial-scale=ane.0"                                />                                                              <meta                http-equiv                                  =                  "X-UA-Compatible"                                content                                  =                  "ie=border"                                />                                                              <title                >              Upload Files                                  </title                >                                                              </head                >                                                              <torso                >                                                              <grade                method                                  =                  "post"                                enctype                                  =                  "multipart/form-data"                                >                                                              <input                type                                  =                  "file"                                name                                  =                  "files[]"                                multiple                />                                                              <input                blazon                                  =                  "submit"                                value                                  =                  "Upload File"                                proper name                                  =                  "submit"                                />                                                              </form                >                                                              <script                src                                  =                  "upload.js"                                >                                                                            </script                >                                                              </torso                >                                                              </html                >                                    

Screen Shot 2018 04 26 at 4 12 29 PM

Sending Grade Data via JavaScript

Right now, clicking submit on the grade doesn't go anywhere. Since we don't have an action that leads to a URL, the grade will just post to itself by default. Since index.html is an html file, not a PHP file, no form processing tin can happen on this page. Instead, we'll send the grade to PHP through JavaScript.

Create a file called upload.js.

First, let's define 2 variables - the URL where we desire to send the information, and the DOM element for the form.

upload.js

                          // Define processing URL and form chemical element              const              url              =              'process.php'              const              form              =              document.              querySelector              (              'form'              )                      

We're going to add together an result listener to watch for the grade beingness submitted, simply we'll forbid the default action from firing.

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

Let's gather the files with the .files belongings, and begin a new FormData() interface.

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

For each file that has been submitted, suspend information technology to the files[] assortment.

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

Finally, use the built-in Fetch API to POST the data to the URL nosotros specified. Print the response to the console (for testing purposes).

                          fetch              (url,              {              method:              'Mail service'              ,              body:              formData,              }              )              .              then              (              (              response              )              =>              {              console.              log              (response)              }              )                      

Here is the completed upload.js.

upload.js

                          const              url              =              'process.php'              const              form              =              certificate.              querySelector              (              'form'              )              form.              addEventListener              (              'submit'              ,              (              eastward              )              =>              {              e.              preventDefault              (              )              const              files              =              document.              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'              ,              body:              formData,              }              )              .              and so              (              (              response              )              =>              {              console.              log              (response)              }              )              }              )                      

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

Create a new file chosen process.php, and print out the contents of the superglobal assortment $_FILES, which will incorporate the information for all our files.

process.php

Once y'all have this file, attempt uploading a few files through the class. I made a phplogo.png and testfile1.txt to exam with, and uploaded the file.

In Developer Tools, under the Console, you lot should run across a response like this:

Developer Tools -> Console

                                                                                                                                                        Response              {              type:              "basic",   url:              "http://localhost:8888/procedure.php",   redirected: faux,   status:              200,   ok: truthful, …              }                      

If y'all encounter status: 200, this means the file hitting the proper URL and the URL exists.

Now in Programmer tools, click on the Network tab. You should see the filename process.php. Click on the file, and click on Response. There, you lot should see the output of print_r($FILES). It volition await something like this:

Developer Tools -> Network -> Response

                          [files]              =>              Assortment              (              [name]              =>              Array              (              [              0              ]              =>              phplogo.png              [              i              ]              =>              testfile1.txt              )              [type]              =>              Array              (              [              0              ]              =>              image/png              [              1              ]              =>              text/plainly              )              [tmp_name]              =>              Assortment              (              [              0              ]              =>              /              private              /              var              /thirty              [              1              ]              =>              /              private              /              var              /yyy              )              [error]              =>              Array              (              [              0              ]              =>              0              [              ane              ]              =>              0              )              [size]              =>              Array              (              [              0              ]              =>              16610              [              1              ]              =>              12              )              )                      

At present nosotros know the proper files, along with all their associated information, have gone through. Success!

Processing Form Data with PHP

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

Get-go, nosotros'll want to make sure the code only runs when a POST asking hits the file.

process.php

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

We also want to make certain files take gone through.

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

Create a directory in the root of your project called uploads. This directory volition need to have 755 permissions to accept incoming files.

At this bespeak, nosotros'll create an array for errors, set the path of the directory where uploads should get, and set the approved extensions.

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

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

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

At present, for each file nosotros'll become 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              (              end              (              explode              (              '.'              ,              $_FILES              [              'files'              ]              [              'name'              ]              [              $i              ]              )              )              )              ;              $file              =              $path              .              $file_name              ;                      

Now we can set a few rules for the files. If the file type in not in the approved listing of extensions, or the file is too large, we'll add it to the fault array. I fix a file size of ii megabytes.

                          if              (              !              in_array              (              $file_ext              ,              $extensions              )              )              {              $errors              [              ]              =              'Extension non 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 ahead and move 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 shut out the for loop, and print out the errors. This will brandish for us in the network tab nosotros used before to see the output of $_FILES.

                          if              (              $errors              )              print_r              (              $errors              )              ;                      

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

process.php

                                          <?php                if                (                $_SERVER                [                'REQUEST_METHOD'                ]                ===                'Mail'                )                {                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'                ]                [                'proper name'                ]                [                $i                ]                ;                $file_tmp                =                $_FILES                [                'files'                ]                [                'tmp_name'                ]                [                $i                ]                ;                $file_type                =                $_FILES                [                'files'                ]                [                'type'                ]                [                $i                ]                ;                $file_size                =                $_FILES                [                'files'                ]                [                'size'                ]                [                $i                ]                ;                $file_ext                =                strtolower                (                end                (                explode                (                '.'                ,                $_FILES                [                'files'                ]                [                'name'                ]                [                $i                ]                )                )                )                ;                $file                =                $path                .                $file_name                ;                if                (                !                in_array                (                $file_ext                ,                $extensions                )                )                {                $errors                [                ]                =                'Extension not immune: '                .                $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 use the form to upload some files, you'll see them in the uploads folder. If yous try to upload a file that'southward as well big or of the wrong blazon, y'all'll see the errors in the Network response.

Conclusion

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

The consummate source is on GitHub.

  • View Source on GitHub

Annotation that this is not a complete, secure, production process. Hither are a few things to accept into consideration:

  • There is no JavaScript side validation. The user should exist shown an error on the front end if their file is of the incorrect type earlier they submit.
  • Dealing with mutiple files with the aforementioned name.
  • This method of error handling is only for the development process.

Thank you for reading. I can likewise brand ane about uploading to Amazon S3 and/or DigitalOcean Spaces if there's interest.