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:
<template>
<picture-input
<!--Props go here-->
></picture-input>
</template>
Here are a few props that we’re going to make use of:
Additionally, the component emits the following events:
Here’s what our code looks like for the file input:
<picture-input
ref="pictureInput"
@change="onChanged"
@remove="onRemoved"
:width="500"
:removable="true"
removeButtonClass="ui red button"
:height="500"
accept="image/jpeg, image/png, image/gif"
buttonClass="ui button primary"
:customStrings="{
upload: '<h1>Upload it!</h1>',
drag: 'Drag and drop your image here'}">
</picture-input>
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 }">
Upload
</button>
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)
.then(response=>{
console.log("Uploaded picture successfully");
})
.catch(err=>{
console.error(err);
});
//...
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)
.then(response=>{
if (response.data.success){
this.image = '';
console.log("Image uploaded successfully ✨");
}
})
.catch(err=>{
console.error(err);
});
}
}
}
//...
💪 Done! Our image upload is working on the frontend. Read-on for how to set this up on a Node.js backend using Express.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi, Thanks for your contribution. Is there a way to add resizing of the images in the UI with this code as starting point? Is there perhaps a library for such features?