Search code examples
vue.jsvuejs2vue-componentvuexfilepond

Why label of file size on filepond show 1kb every file when displaying edit form?


I have a module that has add and edit form. In the add and edit form, the user can upload files. When edit, it will show uploaded files

In add form, it works. When user upload, file size of file displays file size correctly

But my problem is when edit form, each file displays 1kb file size on all files

You can see the problem here:

enter image description here

I use filepond package to upload files

My vue component like this :

<template>
    <b-card>
      <b-form @submit="onSubmit">
        <b-row>
          <b-col cols="8">
            ...
            <b-form-group
              id="fieldset-horizontal"
              label-cols-sm="4"
              label-cols-lg="2"
              content-cols-sm
              content-cols-lg="8"
              label-for="description"
            >
              <template v-slot:label>
                Description
              </template>
              <b-form-input id="description" v-model="description" required  maxlength="100"></b-form-input>
            </b-form-group>
            <b-form-group
              id="fieldset-horizontal"
              label-cols-sm="4"
              label-cols-lg="2"
              content-cols-sm
              content-cols-lg="9"
              label-for="files"
            >
              <template v-slot:label>
                Files 
              </template>
              <file-pond v-if="this.$route.params.id"
                label-idle='Drag and drop files here... or <span class="filepond--label-action"> Browse </span>'
                v-bind:allow-multiple="true"
                v-bind:server="server"
                v-bind:files="files"
              />
              <file-pond v-else
                label-idle='Drag and drop files here... or <span class="filepond--label-action"> Browse </span>'
                v-bind:allow-multiple="true"
                accepted-file-types='application/pdf, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, .xlsx'
                v-bind:server="server"
                v-bind:required="true"
              />
            </b-form-group>
          </b-col>
          <b-col cols="4">
            <b-button type="submit" @click="save" variant="success">Save</b-button>
          </b-col>
        </b-row>
      </b-form>
    </b-card>
  </template>
  
  <script>
  
  import {  mapGetters, mapActions } from "vuex"
  import vueFilePond from "vue-filepond"
  ...
  
  export default {
    data() {
      return {
        files: [],
        server: {
          process: (fieldName, file, metadata, load, error, progress, abort) => {
            if(file.lastModified) { 
              if (this.dataFiles.findIndex(a => a.fileName == file.name) > -1) {
                  error(new Error('More than one file with the same name cannot be attached'));
              }
              else {
                const data = new FormData()
                data.append('files[]', file)
                const CancelToken = axios.CancelToken
                const source = CancelToken.source()
                const config = {
                  method: 'post',
                  url: `${apiUrl}/upload`,
                  data : data,
                  cancelToken: source.token,
                  onUploadProgress: (e) => {
                      progress(e.lengthComputable, e.loaded, e.total)
                  },
                }
                axios(config)
                .then(response => {
                  this.setSaveFile({ 
                    id: response.data.id, 
                    name: response.data.name, 
                    url: response.data.url,
                  })
                  load(response.data.id)
                })
                .catch((thrown) => {
                  if (axios.isCancel(thrown)) {
                    console.log('Request canceled', thrown.message)
                  } else {
                    error('error')
                  }
                })
                return {
                  abort: () => {
                    source.cancel('Operation canceled by the user.')
                  }
                }
              }
            }
            else { /* this will show data file when edit data */
              this.setSaveFile({ 
                id: metadata.id, 
                name: metadata.name, 
                url: metadata.url,
              })
              load(metadata.id)
            }
          },
          revert: (uniqueFileId, load, error) => {
            const type = this.$route.params.id ? 'edit' : 'add'
            this.setDeleteFile({id: uniqueFileId, type: type } )
            error('error')
            load()
          },
        },
      }
    },
    async mounted() {
      if(this.$route.params.id) {
        await this.setEdit(this.$route.params.id)
      }
    },
    computed: {
      ...mapGetters([
        "dataFiles",
        "dataEditSuccess",
      ])
    },
    watch: {
      dataEditSuccess: {
        handler(data) {
          if (this.$route.params.id && data) {
            this.showEditData()
          }
        },
        immediate: true
      }
    },
    methods: {
      ...mapActions([
        "setSaveFile", 
        "setDeleteFile",
        "setEdit",
      ]),    
      showEditData() {
        const data = this.dataEditSuccess
        this.description = data.description
        for (let key in data.files) {
          let filePost = {
            source: data.files[key].name,
            options: {
              metadata: {
                id: data.files[key].id, 
                name: data.files[key].name, 
                url: data.files[key].url,
              },
            },
          }
          this.files.push(filePost)
        }
      },     
    },
    ...
  }
  </script>
  

How can I solve this problem?

Note :

The docs : https://github.com/pqina/vue-filepond

Update :

I make my code in codesandbox like this : https://codesandbox.io/s/vue-filepond-live-demo-forked-0v3r3j

Here it looks the same file size

Actually I can uncomment this script to solve my problem :

file: {
   name: this.filesFromApi[key].name,
   size: this.filesFromApi[key].size,
},

But it makes me unable to fetch metadata in process. So process cannot be called. You can try it and see in the console log


Solution

  • If you're fetching some initial file metadata from an API, couldn't you add that data to vuex at mount time instead of trying to do it through filepond which would give you back the same metadata anyways? Regardless, perhaps listening to one of these events can help you.

    in your component:

    methods: {
        onProcessFile(error, file) {
          console.log('processed file metadata', file.getMetadata())
        },
        onAddFile(error, file) {
          console.log('added file metadata', file.getMetadata())
        }
    },
    
    <file-pond
          name="test"
          ref="pond"
          @processfile="onProcessFile"
          @addfile="onAddFile"
          label-idle="Drop files here or <span class='filepond--label-action'>Browse</span>"
          allow-multiple="true"
          v-bind:files="myFiles"
          v-bind:server="myServer"
        />