banner



How To Allow User To Only Upload Text File Into Form

Introduction

In this commodity, nosotros will talk about how to handle file uploads with VueJs. We will create an images uploader that allow user to upload unmarried or multiple images file by drag and drib or select file dialog.

We will and so upload the selected images and display them appropriately. We volition also learn to filter the upload file type, for instance, we simply let images, do not allow file type like PDF.

Image uploader

  • Sourcecode: https://github.com/chybie/file-upload-vue
  • Demo: https://vue-file-upload-1126b.firebaseapp.com/

File Upload UI & API

File upload consists of two parts: the UI (front-cease) and the API (back-end). We volition be using VueJs to handle the UI part. We need a backend application to take the uploaded files. You may follow the backend tutorials or download and run either ane of these server side application to handle file upload for your backend:-

  • File upload with Hapi.js: https://scotch.io/bar-talk/handling-file-uploads-with-hapi-js, or
  • File upload with Express + Multer: https://scotch.io/tutorials/express-file-uploads-with-multer, or
  • Switch to any cloud solution of your pick (Amazon S3, Google Drive, etc).

We will be using File upload with Hapi.js as our backend throughout this articles. We will also learn the tricks to enable fake upload on the front end-end.

Setup Project with Vue-Cli

We will exist using vue-cli to scaffold Vue.js projects. We will be using the webpack-simple projection template.

                      # install cli            npm            install            vue-cli -yard            # then create projection, with sass            # follow the instructions to install all necessary dependencies            vue init webpack-uncomplicated file-upload-vue                  

Alright, all set. Let's continue to create our component.

File Upload Component

We volition write our code in App.vue. Remove all the car-generated code in the file.

                      <!-- App.vue -->            <!-- HTML Template -->                                          <template              >                                                      <div              id                              =                "app"                            >                                                      <div              class                              =                "container"                            >                        <!--UPLOAD-->                                          <grade              enctype                              =                "multipart/form-data"                            novalidate              v-if                              =                "isInitial || isSaving"                            >                                                      <h1              >            Upload images                              </h1              >                                                      <div              class                              =                "dropbox"                            >                                                      <input              type                              =                "file"                            multiple              :name                              =                "uploadFieldName"                            :disabled                              =                "isSaving"                            @change                              =                "filesChange($event.target.name, $event.target.files); fileCount = $outcome.target.files.length"                            accept                              =                "image/*"                            form                              =                "input-file"                            >                                                      <p              v-if                              =                "isInitial"                            >                        Drag your file(south) here to begin                              <br              >                        or click to browse                                          </p              >                                                      <p              v-if                              =                "isSaving"                            >                        Uploading {{ fileCount }} files...                                          </p              >                                                      </div              >                                                      </form              >                                                      </div              >                                                      </template              >                        <!-- Javascript -->                                          <script              >                                                                                                          </script              >                        <!-- SASS styling -->                                          <way              lang                              =                "scss"                            >                                                                                                          </style              >                              

Notes:-

  1. Our App.vue component consists of 3 office: template (HTML), script (Javascript) and styles (SASS).
  2. Our template has an upload form.
  3. The class aspect enctype="multipart/class-information" is important. To enable file upload, this aspect must exist ready. Learn more most enctype here.
  4. We accept a file input <input type="file" /> to accept file upload. The property multiple indicate it'due south let multiple file upload. Remove it for single file upload.
  5. We volition handle the file input alter result. Whenever the file input change (someone drop or select files), we will trigger the filesChange function and pass in the control name and selected files $consequence.target.files, and then upload to server.
  6. We limit the file input to accept images only with the attribute accept="image/*".
  7. The file input volition be disabled during upload, so user can just drop / select files again after upload complete.
  8. We capture the fileCount of the when file changes. We use the fileCount variable in displaying number of files uploading Uploading {{ fileCount }} files....

Manner our File Upload Component

Now, that's the interesting part. Currently, our component await like this:

File upload component without styling

We need to transform it to look like this:

File upload component with styling

Let's way it!

                      <!-- App.vue -->            ...            <!-- SASS styling -->            <fashion lang="scss">            .dropbox {                          outline              :              2px dashed greyness;              /              *              the nuance box              *              /                                      outline-offset              :              -10px;                          background              :              lightcyan;                          color              :              dimgray;                          padding              :              10px 10px;                          min-height              :              200px;              /              *              minimum height              *              /                                      position              :              relative;                          cursor              :              pointer;            }            .input-file {                          opacity              :              0;              /              *              invisible but it'southward there!              *              /                                      width              :              100%;                          tiptop              :              200px;                          position              :              absolute;                          cursor              :              pointer;            }                          .dropbox              :              hover              {                          background              :              lightblue;              /              *              when mouse over to the drop zone, alter color              *              /                        }            .dropbox p {                          font-size              :              1.2em;                          text-align              :              heart;                          padding              :              50px 0;            }            </way>                  

With only few lines of scss, our component looks prettier at present.

Notes:-

  1. We make the file input invisible by applying opacity: 0 manner. This doesn't hide the file input, information technology just make information technology invisible.
  2. And then, nosotros style the file input parent element, the dropbox css class. Nosotros make it await like a drib file zone surround with dash.
  3. Then, we align the text within dropbox to eye.

File Upload Component Code

Let's continue to code our component.

                      <            !            --            App.vue            --            >            ...            <            !            --            Javascript            --            >            <script>            import            {            upload            }            from            './file-upload.service'            ;            const            STATUS_INITIAL            =            0            ,            STATUS_SAVING            =            1            ,            STATUS_SUCCESS            =            two            ,            STATUS_FAILED            =            three            ;            export            default            {            name            :            'app'            ,            information            (            )            {            return            {            uploadedFiles            :            [            ]            ,            uploadError            :            null            ,            currentStatus            :            aught            ,            uploadFieldName            :            'photos'            }            }            ,            computed            :            {            isInitial            (            )            {            return            this            .currentStatus            ===            STATUS_INITIAL            ;            }            ,            isSaving            (            )            {            return            this            .currentStatus            ===            STATUS_SAVING            ;            }            ,            isSuccess            (            )            {            return            this            .currentStatus            ===            STATUS_SUCCESS            ;            }            ,            isFailed            (            )            {            return            this            .currentStatus            ===            STATUS_FAILED            ;            }            }            ,            methods            :            {            reset            (            )            {            // reset form to initial state            this            .currentStatus            =            STATUS_INITIAL            ;            this            .uploadedFiles            =            [            ]            ;            this            .uploadError            =            null            ;            }            ,            relieve            (            formData            )            {            // upload information to the server            this            .currentStatus            =            STATUS_SAVING            ;            upload            (formData)            .            and so            (            ten            =>            {            this            .uploadedFiles            =            [            ]            .            concat            (x)            ;            this            .currentStatus            =            STATUS_SUCCESS            ;            }            )            .            take hold of            (            err            =>            {            this            .uploadError            =            err.response;            this            .currentStatus            =            STATUS_FAILED            ;            }            )            ;            }            ,            filesChange            (            fieldName,              fileList            )            {            // handle file changes            const            formData            =            new            FormData            (            )            ;            if            (            !fileList.length)            render            ;            // suspend the files to FormData            Array            .            from            (            Array            (fileList.length)            .            keys            (            )            )            .            map            (            ten            =>            {            formData.            suspend            (fieldName,            fileList[ten]            ,            fileList[x]            .proper name)            ;            }            )            ;            // salvage it            this            .            save            (formData)            ;            }            }            ,            mounted            (            )            {            this            .            reset            (            )            ;            }            ,            }            <            /script>                  

Notes:-

  1. Our component volition have a few statuses: STATUS_INITIAL, STATUS_SAVING, STATUS_SUCCESS, STATUS_FAILED, the variable name is pretty expressive themselves.
  2. Subsequently on, we will call the Hapi.js file upload API to upload images, the API have a field telephone call photos. That's our file input field name.
  3. Nosotros handle the file changes with the filesChange function. FileList is an object returned by the files holding of the HTML <input> element. It permit us to access the list of files selected with the <input type="file"> element. Learn more [here]((https://developer.mozilla.org/en/docs/Web/API/FileList).
  4. We and so create a new FormData, and append all our photos files to it. FormData interface provides a way to easily construct a set of cardinal/value pairs representing class fields and their values. Learn more than hither.
  5. The salve part will telephone call our file upload service (hang on, we volition create the service next!). We also set the status co-ordinate to the result.
  6. mountain() is the vue component life cycle hook. During that point, nosotros will set our component status to initial country.

File Upload Service

Let'due south proceed to create our service. Nosotros will be using axios to make HTTP calls.

Install axios

                      # install axios            npm            install            axios --save                  

Service

                      // file-upload.service.js            import            *            as            axios            from            'axios'            ;            const            BASE_URL            =            'http://localhost:3001'            ;            office            upload            (            formData            )            {            const            url            =                          `                              ${                BASE_URL                }                            /photos/upload              `                        ;            return            axios.            post            (url,            formData)            // go data            .            then            (            x            =>            x.information)            // add url field            .            then            (            10            =>            x.            map            (            img            =>            Object.            assign            (            {            }            ,            img,            {            url            :                          `                              ${                BASE_URL                }                            /images/                              ${img.id}                            `                        }            )            )            )            ;            }            export            {            upload            }                  

Cypher much, the code is pretty expressive itself. Nosotros upload the files, wait for the result, map it appropriately.

Yous may run the application now with npm run dev command. Try uploading a couple of images, and information technology'southward working! (Remember to start your backend server)

Brandish Success and Failed Issue

We can upload the files successfully now. Notwithstanding, there's no indication in UI. Let's update our HTML template.

                      <!-- App.vue -->            <!-- HTML Template -->                                          <template              >                                                      <div              id                              =                "app"                            >                                                      <div              class                              =                "container"                            >                        ...class...            <!--SUCCESS-->                                          <div              v-if                              =                "isSuccess"                            >                                                      <h2              >            Uploaded {{ uploadedFiles.length }} file(s) successfully.                              </h2              >                                                      <p              >                                                      <a              href                              =                "javascript:void(0)"                            @click                              =                "reset()"                            >            Upload over again                              </a              >                                                      </p              >                                                      <ul              course                              =                "list-unstyled"                            >                                                      <li              v-for                              =                "item in uploadedFiles"                            >                                                      <img              :src                              =                "detail.url"                            class                              =                "img-responsive img-thumbnail"                            :alt                              =                "item.originalName"                            >                                                      </li              >                                                      </ul              >                                                      </div              >                        <!--FAILED-->                                          <div              5-if                              =                "isFailed"                            >                                                      <h2              >            Uploaded failed.                              </h2              >                                                      <p              >                                                      <a              href                              =                "javascript:void(0)"                            @click                              =                "reset()"                            >            Try again                              </a              >                                                      </p              >                                                      <pre              >            {{ uploadError }}                              </pre              >                                                      </div              >                                                      </div              >                                                      </div              >                                                      </template              >                              

Notes:-

  1. Brandish the uploaded paradigm when upload successfully.
  2. Brandish the error message when upload failed.

Fake the Upload in Front-end

If you are lazy to start the back-end application (Hapi, Express, etc) to handle file upload. Here is a false service to replace the file upload service.

                      // file-upload.simulated.service.js            function            upload            (            formData            )            {            const            photos            =            formData.            getAll            (            'photos'            )            ;            const            promises            =            photos.            map            (            (            10            )            =>            getImage            (x)            .            and then            (            img            =>            (            {            id            :            img,            originalName            :            x.proper noun,            fileName            :            x.name,            url            :            img            }            )            )            )            ;            return            Promise.            all            (promises)            ;            }            part            getImage            (            file            )            {            return            new            Promise            (            (            resolve,              refuse            )            =>            {            const            fReader            =            new            FileReader            (            )            ;            const            img            =            document.            createElement            (            'img'            )            ;            fReader.            onload            =            (            )            =>            {            img.src            =            fReader.result;            resolve            (            getBase64Image            (img)            )            ;            }            fReader.            readAsDataURL            (file)            ;            }            )            }            office            getBase64Image            (            img            )            {            const            sail            =            document.            createElement            (            'sheet'            )            ;            canvas.width            =            img.width;            canvas.height            =            img.height;            const            ctx            =            sail.            getContext            (            '2d'            )            ;            ctx.            drawImage            (img,            0            ,            0            )            ;            const            dataURL            =            sheet.            toDataURL            (            'image/png'            )            ;            return            dataURL;            }            export            {            upload            }                  

Came beyond this solution in this Stackoverflow mail service. Pretty useful. My online demo is using this service.

Basically, what the code do is read the source, draw it in canvas, and save it as information url with the canvas toDataURL function. Larn more than nearly canvas hither.

Now yous can bandy the real service with the fake 1.

                      <            !            --            App.vue            --            >            ...            <            !            --            Javascript            --            >            <script>            // swap as yous need            import            {            upload            }            from            './file-upload.fake.service'            ;            // fake service            // import { upload } from './file-upload.service';   // real service            <            /script>            ...                  

Done! Stop your backend API, refresh your browser, you should see our app is still working, calling simulated service instead.

Bonus: Delay Your Promises

Sometimes, you lot may want to delay the promises to see the state changes. In our case, the file upload may consummate also fast. Let'due south write a helper function for that.

                      // utils.js            // utils to delay promise            function            await            (            ms            )            {            return            (            x            )            =>            {            render            new            Hope            (            resolve            =>            setTimeout            (            (            )            =>            resolve            (x)            ,            ms)            )            ;            }            ;            }            export            {            wait            }                  

And then, you can use it in your component

                      <            !            --            App.vue            --            >            ...            <            !            --            Javascript            --            >            <script>            import            {            look            }            from            './utils'            ;            ...            save            (            formData            )            {            ...            .            upload            (formData)            .            and then            (            expect            (            1500            )            )            // DEV Just: await for 1.5s                        .            then            (            x            =>            {            this            .uploadedFiles            =            [            ]            .            concat            (ten)            ;            this            .currentStatus            =            STATUS_SUCCESS            ;            }            )            ...            }            ,            <            /script>                  

Conclusion

That's information technology. This is how yous can handle file upload without using whatsoever 3rd party libraries and plugins in Vue. Information technology isn't that hard right?

Happy coding!

The UI (Front end-terminate)

  • Sourcecode: https://github.com/chybie/file-upload-vue
  • Demo: https://vue-file-upload-1126b.firebaseapp.com/

The API (Back-end) Tutorials and Sourcode

  • File upload with Hapi.js: https://scotch.io/bar-talk/treatment-file-uploads-with-hapi-js, or
  • File upload with Limited + Multer: https://scotch.io/tutorials/limited-file-uploads-with-multer, or
  • Switch to any cloud solution of your choice (Amazon S3, Google Drive, etc).

Source: https://www.digitalocean.com/community/tutorials/how-to-handle-file-uploads-in-vue-2

Posted by: freedvaunparly.blogspot.com

0 Response to "How To Allow User To Only Upload Text File Into Form"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel