[Vuejs]-Upload an image to a MongoDB database with Vue, TypeScript, Express and Multer

0👍

The idea is to send binary data to backend using FormData and let backend handle the data.

In child component:

<script setup lang="ts">
import { ref } from 'vue';

const movieTitle = ref("");
const moviePoster = ref<File>();


const fileInput = (e: Event): void => {
  const inputElement = <HTMLInputElement>e.target;

  const file = inputElement.files?.[0];

  if (file) {
    moviePoster.value = file;
  }
}

const emit = defineEmits<{
  (e: "movieInfo", poster: File, title: string): void
}>();

const emitImage = () => {
  if (!moviePoster.value) {
    return;
  }

  // Emit the "movieInfo" event with the poster and title
  emit("movieInfo", moviePoster.value, movieTitle.value);
}
</script>

<template>
  <div class="large-container">
    <div class="small-container">
      <form @submit.prevent="emitImage" enctype="multipart/form-data">
        <label for="file">Ladda up film poster</label>
        <input type="file" accept="image/*" @change="fileInput"/>
        <label for="movie-title-input">Film titel</label>
        <input type="text" v-model="movieTitle" name="movie-title-input" />
        <button>Upload image</button>
      </form>
    </div>
  </div>
</template>

And in Parent component:

<script setup lang="ts">
import axios from 'axios';
import { ref } from 'vue';

import FileUploader from 'components/FileUploader.vue';

const savedMovie = ref<any>(null);

const saveMovieInfo = async (moviePoster: File, movieTitle: string) => {

  const formData = new FormData();
  formData.append('poster', moviePoster);
  formData.append('title', movieTitle);


  try {
    const response = await axios.post("http://localhost:3000/movie/savemovie", formData);
    console.log("Movie saved successfully!", response.data);

    const { poster, title } = response.data;

    console.log("poster", poster)

    savedMovie.value = {
      poster: poster,
      title: title,
    };

    console.log("savedMovie.value", savedMovie.value)


  } catch (error) {
    console.log("Failed to save movie:", error);
  }
}
</script>

<template>
  <div>
    <FileUploader @movieInfo="saveMovieInfo"></FileUploader>
    <img :src="savedMovie.poster" alt="Uploaded Image" v-if="savedMovie" />
  </div>
</template>

Your backend should return either the base64 encoded string of image or a url(usually an s3) where the image is stored which can be passed directly in src attribute as you already did in parent component as :src="savedMovie.poster"

Leave a comment