Image Upload in Your Vue.js Apps With vue-picture-input


While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.

File and image uploads are a must-have feature for many non-trivial apps. Lucky for us, it’s easy to setup in Vue apps with vue-picture-input.

Check this post of ours if you’re looking to create your own custom file selector input.


Install vue-picture-input via npm or Yarn:

$ npm install --save vue-picture-input

# or:
$ yarn add vue-picture-input


The vue-picture-input library allows for a variety of usages, and is very simple to use:


  <!--Props go here-->


Here are a few props that we’re going to make use of:

  • ref: We’ll need this to access the base64 image string
  • width, height: Dictate the width and height of the component
  • accept: Used to restrict accepted file types
  • removable: Specifies whether the component can be reset or not

Additionally, the component emits the following events:

  • removed: emitted when picture is detached from component
  • changed: emitted when the selected picture is changed (ie. reselected)

Here’s what our code looks like for the file input:

  removeButtonClass="ui red button"
  accept="image/jpeg, image/png, image/gif"
  buttonClass="ui button primary"
  upload: '<h1>Upload it!</h1>',
  drag: 'Drag and drop your image here'}">


Let’s add a button that will allow us to upload the selected image to our backend.

It basically calls the attemptUpload method when clicked and has the disabled class binding. It’ll only be enabled if there’s a selected image:

<button @click="attemptUpload" v-bind:class="{ disabled: !image }">

Next, we’ll use Axios to make network requests. We’ll also leverage the Formdata API to create a sweet composition for posting image data:

import axios from 'axios';

export default function (url, file, name = 'avatar') {
  if (typeof url !== 'string') {
    throw new TypeError(`Expected a string, got ${typeof url}`);

  // You can add checks to ensure the url is valid, if you wish

  const formData = new FormData();
  formData.append(name, file);
  const config = {
    headers: {
      'content-type': 'multipart/form-data'
  return axios.post(url, formData, config);

The above code accepts a url as the first parameter and a file object as the second parameter then returns a promise. It also sets the header’s content-type to multipart/formdata so our backend API can tell what’s in the pipes.

We can therefore use the above code as so:

import FormDataPost from '/upload';


FormDataPost('http://localhost:8001/user/picture', image)
    console.log("Uploaded picture successfully");


Here’s what our onChanged, onRemoved and attemptUpload methods look like:


methods: {
  onChanged() {
    console.log("New picture loaded");
    if (this.$refs.pictureInput.file) {
      this.image = this.$refs.pictureInput.file;
    } else {
      console.log("Old browser. No support for Filereader API");
  onRemoved() {
    this.image = '';
  attemptUpload() {
    if (this.image){
      FormDataPost('http://localhost:8001/user/picture', this.image)
          if (response.data.success){
            this.image = '';
            console.log("Image uploaded successfully ✨");


💪 Done! Our image upload is working on the frontend. Read-on for how to set this up on a Node.js backend using Express.

Creative Commons License