vuejs2 – How can I upload avatar image and store with localStorage inside server using axios?

I’m Vue Beginner and I’m learning How to store images using link server and local storage. Right Now, What Am I trying to do is I’m trying to make avatar image to upload into my server using axios and add localStorage to getItem avatar image from changeImage method. But, when I load it into localhost, I got an error that says that 404 Not found.

HTML code:

 <div class="text-center p-4 border-bottom">
  <div class="mb-4 profile-user">
    <img
      :src="profile"
      class="rounded-circle avatar-lg img-thumbnail"
      alt="" 
    />
    <button
      type="button"
      class="btn bg-light avatar-xs p-0 rounded-circle profile-photo-edit"
      @click="showModal = true"
    >
      <i class="ri-pencil-fill"></i>
    </button>
  </div>
  <b-modal
    v-model="showModal"
    :title="$t('chat.tabs.settings.modal.title')"
    hide-footer
  >
    <form @submit.prevent="updateprofile">
      <div class="form-group mb-4">
        <label for="updateProfile-input">{{
          $t("chat.tabs.settings.modal.form.profile.label")
        }}</label>
        <b-form-file
          id="file-small"
          placeholder="Choose profile"
          v-on:change="changeImage"
          :class="{
            'is-invalid': submitted && $v.profileDetail.image.$error,
          }"
        ></b-form-file>

        <div
          v-if="submitted && $v.profileDetail.image.$error"
          class="invalid-feedback"
        >
          <span v-if="!$v.profileDetail.image.required">{{
            $t("chat.tabs.settings.modal.form.profile.validation.required")
          }}</span>
        </div>
        <input
          v-if="selectedImage"
          v-model="selectedImage.name"
          type="hidden"
          name="photo"
        />
      </div>
      <div class="form-group mb-4">
        <label for="updateName-input">{{
          $t("chat.tabs.settings.modal.form.name.label")
        }}</label>
        <input
          type="text"
          class="form-control"
          id="updateName-input"
          :placeholder="
            $t('chat.tabs.settings.modal.form.name.placeholder')
          "
          v-model="profileDetail.name"
          :class="{
            'is-invalid': submitted && $v.profileDetail.name.$error,
          }"
        />
        <div
          v-if="submitted && $v.profileDetail.name.$error"
          class="invalid-feedback"
        >
          <span v-if="!$v.profileDetail.name.required">{{
            $t("chat.tabs.settings.modal.form.name.validation.required")
          }}</span>
        </div>
      </div>

      <div class="form-group mb-4">
        <label for="updateEmail-input">{{
          $t("chat.tabs.settings.modal.form.email.label")
        }}</label>
        <input
          type="text"
          class="form-control"
          id="updateEmail-input"
          :placeholder="
            $t('chat.tabs.settings.modal.form.email.placeholder')
          "
          v-model="profileDetail.email"
          :class="{
            'is-invalid': submitted && $v.profileDetail.email.$error,
          }"
        />
        <div
          v-if="submitted && $v.profileDetail.email.$error"
          class="invalid-feedback"
        >
          <span v-if="!$v.profileDetail.email.required">{{
            $t("chat.tabs.settings.modal.form.email.validation.required")
          }}</span>
          <span v-if="!$v.profileDetail.email.email">{{
            $t("chat.tabs.settings.modal.form.email.validation.invalid")
          }}</span>
        </div>
      </div>

      <div class="form-group mb-4">
        <label for="updateLocation-input">{{
          $t("chat.tabs.settings.modal.form.location.label")
        }}</label>
        <input
          type="text"
          class="form-control"
          id="updateLocation-input"
          :placeholder="
            $t('chat.tabs.settings.modal.form.location.placeholder')
          "
          v-model="profileDetail.location"
          :class="{
            'is-invalid': submitted && $v.profileDetail.location.$error,
          }"
        />
        <div
          v-if="submitted && $v.profileDetail.location.$error"
          class="invalid-feedback"
        >
          <span v-if="!$v.profileDetail.location.required">{{
            $t("chat.tabs.settings.modal.form.location.validation.required")
          }}</span>
        </div>
      </div>

      <div class="text-right pt-5 mt-3">
        <b-button variant="link" @click="showModal = false">{{
          $t("chat.tabs.settings.modal.form.button.close")
        }}</b-button>
        <b-button type="submit" variant="primary" class="ml-1">{{
          $t("chat.tabs.settings.modal.form.button.save")
        }}</b-button>
      </div>
    </form>
  </b-modal>
  <h5 class="font-size-16 mb-1 text-truncate">
    {{ username }}
  </h5>
  <p class="text-muted text-truncate mb-1">
    <i
      class="ri-record-circle-fill font-size-10 text-success mr-1 d-inline-block"
    ></i>
    {{ $t("chat.tabs.profile.status") }}
  </p>
</div>

Javascript code:

data() {
    return {
      showModal: false,
      submitted: false,
      form: {
        file: null,
      },
      username: "",
      profile: "",
      useremail: "",
      userlocation: "",
      profileDetail: {
        image: null,
        name: "",
        email: "",
        location: "",
      },
      allowableTypes: ["jpg", "jpeg", "png", "gif"],
      maximumSize: 5000000,
      selectedImage: null,
      image: null,
      options: {
        url: "./assets/images/users/",
        type: "POST",
      },
    };
  },

components: { simplebar },
  validations: {
    profileDetail: {
      image: { required },
      name: { required },
      email: { required, email },
      location: { required },
    },
  },

methods: {
    updateprofile() {
      this.submitted = true;
      // stop here if form is invalid
      this.$v.$touch();
      if (this.$v.$invalid) {
        return;
      } else {
        this.profile = this.image;
        this.username = this.profileDetail.name;
        this.useremail = this.profileDetail.email;
        this.userlocation = this.profileDetail.location;
        this.showModal = false;
      }
      this.submitted = false;
      this.form = {};
    },

    validate(image) {
      if (
        !this.allowableTypes.includes(
          image.name
            .split(".")
            .pop()
            .toLowerCase()
        )
      ) {
        alert(
          `Sorry you can only upload ${this.allowableTypes
            .join("|")
            .toUpperCase()} files.`
        );
        return false;
      }
      if (image.size > this.maximumSize) {
        alert("Sorry File size exceeding from 5 Mb");
        return false;
      }
      return true;
    },
    onImageError(err) {
      console.log(err, "do something with error");
    },
    changeImage($event) {
      this.selectedImage = $event.target.files[0];
      this.profileDetail.image = $event.target.files[0];
      
      //validate the image
      if (!this.validate(this.selectedImage)) return;
      // create a form
      const form = new FormData();
      form.append("file", this.selectedImage);
      

      // store image with local storage
      axios
        .post("./assets/images/users/", { data: form })
        .then(this.createImage = localStorage.getItem("file"))
        .catch(this.onImageError);
      },

    createImage() {
      const reader = new FileReader();
      reader.onload = (e) => {
        this.image = e.target.result;
      };
      reader.readAsDataURL(this.selectedImage);
    },
  },

404 not found error:

enter image description here

Folder to store image:

enter image description here

  data() {
    return {
      showModal: false,
      submitted: false,
      form: {
        file: null,
      },
      username: "",
      profile: "",
      useremail: "",
      userlocation: "",
      profileDetail: {
        image: null,
        name: "",
        email: "",
        location: "",
      },
      allowableTypes: ["jpg", "jpeg", "png", "gif"],
      maximumSize: 5000000,
      selectedImage: null,
      image: null,
      options: {
        url: "./assets/images/users/",
        type: "POST",
      },
    };
  },
  components: { simplebar },
  validations: {
    profileDetail: {
      image: { required },
      name: { required },
      email: { required, email },
      location: { required },
    },
  },
  methods: {
    updateprofile() {
      this.submitted = true;
      // stop here if form is invalid
      this.$v.$touch();
      if (this.$v.$invalid) {
        return;
      } else {
        this.profile = this.image;
        this.username = this.profileDetail.name;
        this.useremail = this.profileDetail.email;
        this.userlocation = this.profileDetail.location;
        this.showModal = false;
      }
      this.submitted = false;
      this.form = {};
    },

    validate(image) {
      if (
        !this.allowableTypes.includes(
          image.name
            .split(".")
            .pop()
            .toLowerCase()
        )
      ) {
        alert(
          `Sorry you can only upload ${this.allowableTypes
            .join("|")
            .toUpperCase()} files.`
        );
        return false;
      }
      if (image.size > this.maximumSize) {
        alert("Sorry File size exceeding from 5 Mb");
        return false;
      }
      return true;
    },
    onImageError(err) {
      console.log(err, "do something with error");
    },
    changeImage($event) {
      this.selectedImage = $event.target.files[0];
      this.profileDetail.image = $event.target.files[0];
      
      //validate the image
      if (!this.validate(this.selectedImage)) return;
      // create a form
      const form = new FormData();
      form.append("file", this.selectedImage);
      

      // store image with local storage
      axios
        .post("./assets/images/users/", { data: form })
        .then(this.createImage = localStorage.getItem("file"))
        .catch(this.onImageError);
      },

    createImage() {
      const reader = new FileReader();
      reader.onload = (e) => {
        this.image = e.target.result;
      };
      reader.readAsDataURL(this.selectedImage);
    },
  },
<div class="text-center p-4 border-bottom">
      <div class="mb-4 profile-user">
        <img
          :src="https://stackoverflow.com/questions/72442863/profile"
          class="rounded-circle avatar-lg img-thumbnail"
          alt="" 
        />
        <button
          type="button"
          class="btn bg-light avatar-xs p-0 rounded-circle profile-photo-edit"
          @click="showModal = true"
        >
          <i class="ri-pencil-fill"></i>
        </button>
      </div>
      <b-modal
        v-model="showModal"
        :title="$t('chat.tabs.settings.modal.title')"
        hide-footer
      >
        <form @submit.prevent="updateprofile">
          <div class="form-group mb-4">
            <label for="updateProfile-input">{{
              $t("chat.tabs.settings.modal.form.profile.label")
            }}</label>
            <b-form-file
              id="file-small"
              placeholder="Choose profile"
              v-on:change="changeImage"
              :class="{
                'is-invalid': submitted && $v.profileDetail.image.$error,
              }"
            ></b-form-file>

            <div
              v-if="submitted && $v.profileDetail.image.$error"
              class="invalid-feedback"
            >
              <span v-if="!$v.profileDetail.image.required">{{
                $t("chat.tabs.settings.modal.form.profile.validation.required")
              }}</span>
            </div>
            <input
              v-if="selectedImage"
              v-model="selectedImage.name"
              type="hidden"
              name="photo"
            />
          </div>
          <div class="form-group mb-4">
            <label for="updateName-input">{{
              $t("chat.tabs.settings.modal.form.name.label")
            }}</label>
            <input
              type="text"
              class="form-control"
              id="updateName-input"
              :placeholder="
                $t('chat.tabs.settings.modal.form.name.placeholder')
              "
              v-model="profileDetail.name"
              :class="{
                'is-invalid': submitted && $v.profileDetail.name.$error,
              }"
            />
            <div
              v-if="submitted && $v.profileDetail.name.$error"
              class="invalid-feedback"
            >
              <span v-if="!$v.profileDetail.name.required">{{
                $t("chat.tabs.settings.modal.form.name.validation.required")
              }}</span>
            </div>
          </div>

          <div class="form-group mb-4">
            <label for="updateEmail-input">{{
              $t("chat.tabs.settings.modal.form.email.label")
            }}</label>
            <input
              type="text"
              class="form-control"
              id="updateEmail-input"
              :placeholder="
                $t('chat.tabs.settings.modal.form.email.placeholder')
              "
              v-model="profileDetail.email"
              :class="{
                'is-invalid': submitted && $v.profileDetail.email.$error,
              }"
            />
            <div
              v-if="submitted && $v.profileDetail.email.$error"
              class="invalid-feedback"
            >
              <span v-if="!$v.profileDetail.email.required">{{
                $t("chat.tabs.settings.modal.form.email.validation.required")
              }}</span>
              <span v-if="!$v.profileDetail.email.email">{{
                $t("chat.tabs.settings.modal.form.email.validation.invalid")
              }}</span>
            </div>
          </div>

          <div class="form-group mb-4">
            <label for="updateLocation-input">{{
              $t("chat.tabs.settings.modal.form.location.label")
            }}</label>
            <input
              type="text"
              class="form-control"
              id="updateLocation-input"
              :placeholder="
                $t('chat.tabs.settings.modal.form.location.placeholder')
              "
              v-model="profileDetail.location"
              :class="{
                'is-invalid': submitted && $v.profileDetail.location.$error,
              }"
            />
            <div
              v-if="submitted && $v.profileDetail.location.$error"
              class="invalid-feedback"
            >
              <span v-if="!$v.profileDetail.location.required">{{
                $t("chat.tabs.settings.modal.form.location.validation.required")
              }}</span>
            </div>
          </div>

          <div class="text-right pt-5 mt-3">
            <b-button variant="link" @click="showModal = false">{{
              $t("chat.tabs.settings.modal.form.button.close")
            }}</b-button>
            <b-button type="submit" variant="primary" class="ml-1">{{
              $t("chat.tabs.settings.modal.form.button.save")
            }}</b-button>
          </div>
        </form>
      </b-modal>
      <h5 class="font-size-16 mb-1 text-truncate">
        {{ username }}
      </h5>
      <p class="text-muted text-truncate mb-1">
        <i
          class="ri-record-circle-fill font-size-10 text-success mr-1 d-inline-block"
        ></i>
        {{ $t("chat.tabs.profile.status") }}
      </p>
    </div>

My question right now is this possible to way to store image using ./assets/images/users/ link?

Leave a Comment