I am using Vue 3.0. So first, we will install the Vue.js using Vue CLI, and then we will install the vue-dropzone library. Then configure it, and we are ready to accept the file.
Vue File Upload Using vue-dropzone
Dropzone.js is an open-source library providing drag-and-drop file uploads with image previews. DropzoneJS is lightweight, doesn’t depend on any other library (like jQuery), and is highly customizable.
The vue-dropzone is a vue component implemented on top of Dropzone.js.
First, install the Vue using Vue CLI.
Step 1: Install Vue.js using Vue CLI.
Go to your terminal and hit the following command.
npm install -g @vue/cli or yarn global add @vue/cli
If you face any error, try running the command as an administrator.
Now, we need to generate the necessary scaffold. So type the following command.
vue create vuedropzone
It will install the scaffold.
Open the project in your favorite editor. Mine is Visual Studio Code.
cd vuedropzone code .
Step 2: Install vue-dropzone.
I am using the Yarn package manager. So let’s install using Yarn. You can use NPM, also. It does not matter.
yarn add vue2-dropzone or npm install vue2-dropzone
Okay, now we need to add one css file with the above package. Now, vue cli uses css loader, so we can directly import in the src >> main.js entry file.
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App) }).$mount('#app') import 'vue2-dropzone/dist/vue2Dropzone.css'
If importing css is not working for you, then you need to install that CSS file manually.
Copy this vue2Dropzone.css file’s content.
Create one file inside the src >> assets folder, create one css file called vuedropzone.css and paste the content there.
Import this css file inside src >> App.vue file.
<style lang="css"> @import './assets/vuedropzone.css'; </style>
Now, it should include in our application.
Step 3: Upload an Image.
Our primary boilerplate has one ready-made component called HelloWorld.vue inside src >> components folder. Now, create one more file called FileUpload.vue.
Add the following code to FileUpload.vue file.
// FileUpload.vue <template> <div id="app"> <vue-dropzone id="upload" :options="config"></vue-dropzone> </div> </template> <script> import vueDropzone from "vue2-dropzone"; export default { data: () => ({ config: { url: "https://appdividend.com" } }), components: { vueDropzone } }; </script>
Here, our API endpoint is https://appdividend.com. It is the point where we will hit the POST route and store our image, but it is my blog’s homepage, so it will not work anyway. But let me import this file into App.vue component and see what happens.
// App.vue <template> <div id="app"> <FileUpload /> </div> </template> <script> import FileUpload from './components/FileUpload.vue' export default { name: 'app', components: { FileUpload } } </script> <style lang="css"> @import './assets/vuedropzone.css'; </style>
Now, start the development server using the following command. It will open up URL: http://localhost:8080.
npm run serve
Now, after uploading the image, we can see that the image upload is failed due to the wrong POST request endpoint.
Step 4: Create Laravel API for the endpoint.
Install the Laravel.
After that, we configure the database in the .env file and use MySQL database.
We need to create one model and migration file to store the image. So let us install the following command inside the Laravel project.
php artisan make:model Image -m
It will create both the Image model and create_images_table.php migrations file.
Now, open the migrations file and add the schema to it.
// create_images_table.php public function up() { Schema::create('images', function (Blueprint $table) { $table->increments('id'); $table->string('image_name'); $table->timestamps(); }); }
Now, migrate the database table using the following command.
php artisan migrate
It creates the table in the database.
Now, we need to add a laravel-cors package to prevent cross-site-allow-origin errors. Go to the Laravel root and enter the following command to install it.
composer require barryvdh/laravel-cors
Configure it in the config >> app.php file.
Barryvdh\Cors\ServiceProvider::class,
Add the middleware inside app >> Http >> Kernel.php file.
// Kernel.php protected $middleware = [ \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \App\Http\Middleware\TrustProxies::class, \Barryvdh\Cors\HandleCors::class, ];
Step 5: Define the API route and method to store the image.
First, create an ImageController.php file using the following command.
php artisan make:controller ImageController
Define the store method. Also, create one images folder inside the public directory because we will store an image inside it.
Right now, I have written the store function that handles one image at a time. So do not upload multiple photos at a time; otherwise, it will break.
// ImageController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Image; class ImageController extends Controller { public function store(Request $request) { if($request->file('file')) { $image = $request->file('file'); $name = time().$image->getClientOriginalName(); $image->move(public_path().'/images/', $name); } $image= new Image(); $image->image_name = $name; $image->save(); return response()->json(['success' => 'You have successfully uploaded an image'], 200); } }
Go to the routes >> api.php file and add the following route.
// api.php Route::post('image', 'ImageController@store');
Step 6: Edit FileUpload.vue component.
We need to add the correct Post request API endpoint in FileUpload.vue component.
// FileUpload.vue <template> <div id="app"> <vue-dropzone id="drop1" :options="config" @vdropzone-complete="afterComplete"></vue-dropzone> </div> </template> <script> import vueDropzone from "vue2-dropzone"; export default { data: () => ({ config: { url: "http://localhost:8000/api/image", } }), components: { vueDropzone }, methods: { afterComplete(file) { console.log(file); } } }; </script>
Now, save the file and try to upload an image. If everything is okay, then you will be able to save the image on the Laravel web server as well as save the name in the database as well.
You can also verify on the server side by checking the database entry and the images folder in which we have saved the image.
Step 7: More vue-dropzone configuration.
The only required options are url, but there are many more you can use.
For example, let’s say you want:
- A maximum of 4 files
- 2 MB max file size
- Sent in chunks of 500 bytes
- Set a custom thumbnail size of 150px
- Make the uploaded items cancelable and removable (by default, they’re not)
export default { data: () => ({ dropOptions: { url: "https://httpbin.org/post", maxFilesize: 5, // MB maxFiles: 5, chunking: true, chunkSize: 400, // Bytes thumbnailWidth: 100, // px thumbnailHeight: 100, addRemoveLinks: true } }) // ... }
That’s it for this tutorial. Thanks for taking it.
Nice tutorial, many thanks!
After the first run (end of step 3), i get the following error in the terminal where “npm run serve” is running:
“This dependency was not found:
* -!../node_modules/css-loader/ (…)”
Please include css-loader, or if you are using vue-cli then go to your root and type: npm install
I got it to work meanwhile, but how can I get the filename of the uploaded file in the frontend?
The “file” object in the vue component’s method “afterComplete” contains this file name:
file.upload.filename = “2018-05-10 09.53.46.jpg”
However, the actual image name on the Laravel side is “15261126372018-05-10 09.53.46.jpg”
I need to be able to reference this file in the frontend app.
Thanks again.
What about authentication?
I use Laravel Passport and Axios on the frontend is configured to add the “X-XSRF-TOKEN” to the header of the API request.
Is that also possible with DropZone? I found the “WithCredentials” config setting, but there is no documentation how to use it.
I found the proper setting, it’s called ‘headers’!
Have you find out how to get Laravel’s file name?
You can return your image data in to the response
like
return response()->json([
‘success’ => ‘You have successfully uploaded an image’
‘name=> $name
], 200);
Now at vue side
in afterComplete(from above example) method
just do
console.log(file.xhr.response) –> this response is which you have return from Laravel.
hello
can you please make a tutorial for vue file upload using vue-dropzone in vuejs and yii(instead of laravel)
thanks in advance.
Thanks! you saved my day! All my issues were related to be using the web routes instead of api routes.
I appreciate it!
Where is the vue2Dropzone.css? css file is 404 now. Please guide me.