skip to Main Content

I am using Vuejs to create an upload form.

Issue is that when I upload with key of object, backend server receives empty request:
like axios.postForm(app_url() + 'api/upload', { files: e.target.files[key] }, api_config())

But when I upload with following expression (Whole files together) It works correctly:
like axios.postForm(app_url() + 'api/upload', { files: e.target.files }, api_config())

What is reason of this problem? and how can I send files separate and simultaneous to server?

Here is then code:

<script setup>
import uploadIcon from '../assets/images/direct-inbox.png';
import axios from 'axios';
import app_url from '../customJavascript/app_url';
import api_config from '../customJavascript/api_config';

const changeFile = (e) => {

  const all = [];

  for (const key in e.target.files) {

    if (typeof e.target.files[key] == 'object') {
      all.push(axios.postForm(app_url() + 'api/upload', { files: e.target.files }, api_config()));
    }

  }

  axios.all(all)
    .then(axios.spread((data1, data2) => {
      console.log('data1', data1, 'data2', data2)
    }));

}
</script>

<template>
  <div class="main-card">
    <p class="main-card-title">upload file</p>

    <div class="mt-6 flex justify-center">


      <div class="upload-card clickable focus:shadow-none">

        <div class="relative text-center h-full flex flex-col justify-center align-center">
          <input type="file" @change="changeFile"
            class="rounded-2xl cursor-pointer absolute right-0 top-0 w-full h-full opacity-0" multiple />
        </div>

      </div>

    </div>
  </div>
</template>


<style>
.upload-card {
  @apply w-11/12 lg:w-5/12 h-60 lg:h-60 rounded-2xl border-2 border-lightblue bg-white hover:shadow-lg;
}
.upload-card:hover button {
  @apply bg-primary;
}
</style>

I put code out side of loop and send request with just a static index variable, I expected maybe loop caused this issue but It wasn’t.

2

Answers


  1. looks like your server expects an array of files.
    if you want to upload the files with separate requests you need to have this: { files: [e.target.files[key]] }

    PS: you can also use filter + map functions:

    const all = e.target.files
       .filter((file) => typeof file === 'object')
       .map((file) => axios.postForm(app_url() + 'api/upload', { files: [file] }, api_config());
    
    Login or Signup to reply.
  2. In your code, e.target.files is a FileList [w3c] object. This interface is a list of File [w3c] objects.

    The iteration does not do what you think it does.

    for (const key in e.target.files) // [for ••• in [mdn] statement]

    It iterates a specified variable over all the enumerable properties of the FileList. See example [mdn].

    To loop over the values of the FileList correctly, use:

    for (const file of e.target.files) // [for ••• of [mdn] statement] 

    Now it iterates over a sequence of values sourced from the FileList object.

    Lastly, does this test true? [1]

    if (typeof e.target.files[key] == 'object')

    Technically, you are iterating over the enumerable properties of the FileList and testing if each property is an object.

    I’ll have to stop here. [2]


    To upload data over HTTP, the type of the data should be correctly specified to tell the server how to handle the incoming data. You will specify this in the header of your request. The header Content-Type is often used with a value of multipart/form-data. Most servers know what to do when they receive this.

    Fortunately axios handles the stress for you when you use axios.postForm().


    [1] I had a feeling this will be asked.

    [2] I stopped there because I couldn’t justify to myself why the code after the if statement is even there.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search