No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Uploader with Axios

    Help
    8
    12
    6398
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • valasek
      valasek last edited by

      Hi,

      I am using centralized communication backend (GO) using Axios. How can I use Uploader with Axios? Loading just one file and want to trigger upload after uploading that one file.
      Can this be achieved just by using QUploader provided events or methods? Or should I extend QUploaderBase?

      <q-uploader
        label="Upload"
        auto-upload
        accept=".zip"
        :max-file-size="5000"
        style="max-width: 300px"
        />
      

      and my upload function

      upload (file) {
            const fr = new FileReader()
            fr.readAsDataURL(file)
            fr.addEventListener('load', () => {
              this.uploadedImage = fr.result
              this.uploadFile = file
              const admin = this
              const formData = new FormData()
              formData.append('uploadFile', this.uploadFile)
              api.apiClient.post('/api/upload/data', formData)
                .then(response => {
                  this.$store.dispatch('context/setNotification', { text: 'Restore successfully completed', type: 'success' })
                  // post restore processing
                })
                .catch(function (e) {
                  admin.$store.dispatch('context/setNotification', { text: 'Couldn\'t upload file: ' + e.response.data, type: 'error' }, { root: true })
                  console.log(e, e.response) /* eslint-disable-line no-console */
                })
            })
          },
      
      1 Reply Last reply Reply Quote 0
      • patryckx
        patryckx last edited by

        @valasek There are some events that are issued as @added, @finished, @uploaded.

        Look in the documentation: https://quasar.dev/vue-components/uploader#QUploader-API

        1 Reply Last reply Reply Quote 0
        • metalsadman
          metalsadman last edited by metalsadman

          @valasek make use of the upload-factory. edit. so it’s removed now and it’s called factory prop in v1, the new one doesn’t pass the updateProgress function tho :(.

          1 Reply Last reply Reply Quote 0
          • marcelo
            marcelo last edited by

            I am having a similar issue.
            I have a global axios configured to deal with authentication and QUploader uses direct XHRRequests.
            Even if a do an ugly way to set all security headers in factory function, it gives weird errors os server side.
            If I use the global axios for the same request it works… but then I can not use the (nice) QUploader UI.

            There is any way to tell QUploader to use the global axios instance?

            1 Reply Last reply Reply Quote 0
            • metalsadman
              metalsadman last edited by metalsadman

              Use factory prop passing your own upload function https://quasar.dev/vue-components/uploader#Factory-function.

              1 Reply Last reply Reply Quote 0
              • marcelo
                marcelo last edited by

                As I understand from docs, factory prop is used to dynamically pass parameters to uploader, not to process the upload in this function (because Quasar will do a request using the values passed by the factory function)
                This is not the same as using the global axios instance (plugin configured on boot).
                If I manually handle the uploader inside the factory, how Quasar will know about it?
                Are the docs incomplete or I just didn’t understand it?

                stukki 1 Reply Last reply Reply Quote 0
                • metalsadman
                  metalsadman last edited by metalsadman

                  @marcelo It seems so, I haven’t tried this new uploader, before v1 there used to be a upload-factory https://v0-17.quasar-framework.org/components/uploader.html#Upload-Factory to handle the upload yourself, I think the new way now is by this https://quasar.dev/vue-components/uploader#Supporting-other-services extending the component and handling the methods on your own in your extended component, see the script below in that section on how. The QUploaderBase source https://github.com/quasarframework/quasar/blob/dev/ui/src/components/uploader/QUploaderBase.js.

                  1 Reply Last reply Reply Quote 0
                  • stukki
                    stukki @marcelo last edited by

                    @marcelo I faced nearly the same problem and find a solution that works for me (Authentication not yet implemented). I’m not sure if it best practice but I also wanted the uploader to be reusable within other components and wanted to use the QUploader component because of its additional features like thumbnail, display file-size…

                    I let the url parameter blank.
                    I get the selected file’s details through the @added-event and safe it in a vuex store
                    I trigger the upload - method outside the QUploader component

                    In my uploader.vue file:

                    <template>
                      <div class="row justify-center items-center">
                        <div>
                          <div class="row justify-between items-center q-px-sm" v-if="showUploadButton === false">
                            <div class="fa-text-dark-light">{{ deleteMethodString }}</div>
                            <div>
                    //youNeed
                              <q-btn
                                @click="deleteFile()"
                                class="q-pl-sm"
                                color="negative"
                                flat
                                icon="ion-ios-trash"
                                round
                              >
                              </q-btn>
                            </div>
                          </div>
                    //youNeed
                          <q-uploader
                            :accept="acceptedFileTypes"
                            :label="uploaderLabel"
                            @added="fileSelected"
                            @removed="fileRemoved"
                            color="grey-1"
                            flat
                            hide-upload-btn
                            square
                            text-color="accent"
                            url=""
                          >
                          </q-uploader>
                        </div>
                        <div class="q-mt-xl" v-if="showUploadButton === true">
                    //youNeed
                          <q-btn
                            :label="$t('message.general.upload')"
                            @click="upload()"
                            color="accent"
                            outline
                          >
                          </q-btn>
                        </div>
                      </div>
                    </template>
                    
                    <script>
                    import { mapGetters, mapState, mapActions } from 'vuex'
                    export default {
                      name: 'uploaderComponent',
                      components: {
                      },
                      data () {
                        return {
                    //youNeed
                          selectedFile: false,
                          uploaderLabel: 'Select a File',
                          showUploadButton: false,
                          deleteMethodString: ''
                        }
                      },
                    //youNeed
                      watch: {
                        selectedFile () {
                          if (this.selectedFile === true) {
                            this.uploaderLabel = ''
                            this.showUploadButton = true
                          } else {
                            this.showUploadButton = false
                          }
                        }
                      },
                      mounted () {
                        this.deleteMethodString = this.deleteString
                        this.uploaderLabel = this.uploadLabel
                      },
                      computed: {
                        ...mapGetters({
                          currentLanguage: 'language/statusCurrentLanguage'
                        }),
                        ...mapState({
                          fileUploadCompleted: state => state.uploader.fileUploadCompleted,
                          concern: state => state.uploader.propsForFileUpload.concern,
                          acceptedFileTypes: state => state.uploader.propsForFileUpload.acceptedFileTypes,
                          deleteString: state => state.uploader.propsForFileUpload.stringForDeleteMethod,
                          uploadLabel: state => state.uploader.propsForFileUpload.uploaderLabel
                        })
                      },
                      methods: {
                        ...mapActions({
                    //youNeed
                          fileUpload: 'uploader/ActionFileUpload',
                          uploaderDialogTrigger: 'app/ActionUploaderDialog',
                          fileDelete: 'uploader/uploaderFileDelete'
                        }),
                    //youNeed
                        fileSelected (files) {
                          if (files.length !== 0) {
                            this.selectedFile = true
                          }
                          this.$store.commit('uploader/MutationFileSelected', files[0])
                        },
                    //youNeed
                        fileRemoved () {
                          this.selectedFile = false
                        },
                    //youNeed
                        upload () {
                          this.fileUpload()
                        },
                        deleteFile () {
                          this.fileDelete()
                          this.uploaderDialogTrigger(false)
                        }
                      }
                    }
                    </script>
                    

                    vuex

                    // MUTATION
                    export const MutationFileSelected = (state, payload) => {
                      state.fileSelected = payload
                    }
                    
                    //ACTION
                    export const ActionFileUpload = (context) => {
                      let uploaderProps = context.state.propsForFileUpload.concern
                      let id = ''
                      let uploadUrl = ''
                      let uploaData = new FormData()
                      if (uploaderProps === 'clubLogoUpload') {
                        id = context.rootGetters['clubEdit/getterHomeClubId']
                        uploadUrl = 'homeclub/putLogo/'
                    //youNeed
                        uploaData.append('file', context.state.fileSelected)
                      }
                    //youNeed
                      Vue.prototype.$axios.post(process.env.API + uploadUrl + id, uploaData, {
                        headers: {
                          'Content-Type': undefined
                        },
                        onUploadProgress: function (progressEvent) {
                          let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
                          context.commit('MutationOnUploadProgress', percentCompleted)
                        }
                      })
                        .then(function (response) {
                          if (response.status === 200) {
                            console.log(response)
                            context.dispatch('app/ActionUploaderDialog', false, {root: true})
                            context.dispatch('ActionAfterFileUpload')
                            if (context.rootGetters['language/statusCurrentLanguage'] === 'en') {
                              Notify.create({
                                type: 'positive',
                                icon: 'img:statics/icons/check.svg',
                                color: 'positive',
                                timeout: 1000,
                                position: 'center',
                                message: 'Yeah. File uploaded. Great Job!'
                              })
                            }
                            if (context.rootGetters['language/statusCurrentLanguage'] === 'zh') {
                              Notify.create({
                                type: 'positive',
                                icon: 'img:statics/icons/check.svg',
                                color: 'positive',
                                timeout: 1000,
                                position: 'center',
                                message: 'Yeah. File uploaded. Great Job! -ZH'
                              })
                            }
                          }
                        })
                        .catch(function (error) {
                          console.log(error)
                        })
                    }
                    

                    I think there’s a lot of stuff you won’t need but I didn’t want to tear it up. This solution enables me to use axios’s features, which are for me are a bit easier to handle.

                    I’ve prefixed the essential parts I assume you need with //youNeed

                    If there is anyone who might have an idea to improve this solution, I’d be appreciated

                    M M 2 Replies Last reply Reply Quote -1
                    • valasek
                      valasek last edited by

                      @stukki that you a lot, I will try on my project and will get back to you how this worked.

                      1 Reply Last reply Reply Quote 0
                      • M
                        manur @stukki last edited by

                        @stukki Thanks a lot, I try on my project but 3 vuex errors returns when send a file (store/uploader/action) :

                        [vuex] unknown local mutation type: MutationOnUploadProgress, global type: uploader/MutationOnUploadProgress
                        [vuex] unknown action type: app/ActionUploaderDialog
                        [vuex] unknown local action type: ActionAfterFileUpload, global type: uploader/ActionAfterFileUpload
                        

                        Could you help me ?

                        1 Reply Last reply Reply Quote 0
                        • L
                          LIANG FENG last edited by

                          I have the same problem. Is there any solution?

                          1 Reply Last reply Reply Quote 0
                          • M
                            mecjos @stukki last edited by

                            @stukki said in Uploader with Axios:

                            @marcelo I faced nearly the same problem and find a solution that works for me (Authentication not yet implemented). I’m not sure if it best practice but I also wanted the uploader to be reusable within other components and wanted to use the QUploader component because of its additional features like thumbnail, display file-size…

                            I let the url parameter blank.
                            I get the selected file’s details through the @added-event and safe it in a vuex store
                            I trigger the upload - method outside the QUploader component

                            In my uploader.vue file:

                            <template>
                              <div class="row justify-center items-center">
                                <div>
                                  <div class="row justify-between items-center q-px-sm" v-if="showUploadButton === false">
                                    <div class="fa-text-dark-light">{{ deleteMethodString }}</div>
                                    <div>
                            //youNeed
                                      <q-btn
                                        @click="deleteFile()"
                                        class="q-pl-sm"
                                        color="negative"
                                        flat
                                        icon="ion-ios-trash"
                                        round
                                      >
                                      </q-btn>
                                    </div>
                                  </div>
                            //youNeed
                                  <q-uploader
                                    :accept="acceptedFileTypes"
                                    :label="uploaderLabel"
                                    @added="fileSelected"
                                    @removed="fileRemoved"
                                    color="grey-1"
                                    flat
                                    hide-upload-btn
                                    square
                                    text-color="accent"
                                    url=""
                                  >
                                  </q-uploader>
                                </div>
                                <div class="q-mt-xl" v-if="showUploadButton === true">
                            //youNeed
                                  <q-btn
                                    :label="$t('message.general.upload')"
                                    @click="upload()"
                                    color="accent"
                                    outline
                                  >
                                  </q-btn>
                                </div>
                              </div>
                            </template>
                            
                            <script>
                            import { mapGetters, mapState, mapActions } from 'vuex'
                            export default {
                              name: 'uploaderComponent',
                              components: {
                              },
                              data () {
                                return {
                            //youNeed
                                  selectedFile: false,
                                  uploaderLabel: 'Select a File',
                                  showUploadButton: false,
                                  deleteMethodString: ''
                                }
                              },
                            //youNeed
                              watch: {
                                selectedFile () {
                                  if (this.selectedFile === true) {
                                    this.uploaderLabel = ''
                                    this.showUploadButton = true
                                  } else {
                                    this.showUploadButton = false
                                  }
                                }
                              },
                              mounted () {
                                this.deleteMethodString = this.deleteString
                                this.uploaderLabel = this.uploadLabel
                              },
                              computed: {
                                ...mapGetters({
                                  currentLanguage: 'language/statusCurrentLanguage'
                                }),
                                ...mapState({
                                  fileUploadCompleted: state => state.uploader.fileUploadCompleted,
                                  concern: state => state.uploader.propsForFileUpload.concern,
                                  acceptedFileTypes: state => state.uploader.propsForFileUpload.acceptedFileTypes,
                                  deleteString: state => state.uploader.propsForFileUpload.stringForDeleteMethod,
                                  uploadLabel: state => state.uploader.propsForFileUpload.uploaderLabel
                                })
                              },
                              methods: {
                                ...mapActions({
                            //youNeed
                                  fileUpload: 'uploader/ActionFileUpload',
                                  uploaderDialogTrigger: 'app/ActionUploaderDialog',
                                  fileDelete: 'uploader/uploaderFileDelete'
                                }),
                            //youNeed
                                fileSelected (files) {
                                  if (files.length !== 0) {
                                    this.selectedFile = true
                                  }
                                  this.$store.commit('uploader/MutationFileSelected', files[0])
                                },
                            //youNeed
                                fileRemoved () {
                                  this.selectedFile = false
                                },
                            //youNeed
                                upload () {
                                  this.fileUpload()
                                },
                                deleteFile () {
                                  this.fileDelete()
                                  this.uploaderDialogTrigger(false)
                                }
                              }
                            }
                            </script>
                            

                            vuex

                            // MUTATION
                            export const MutationFileSelected = (state, payload) => {
                              state.fileSelected = payload
                            }
                            
                            //ACTION
                            export const ActionFileUpload = (context) => {
                              let uploaderProps = context.state.propsForFileUpload.concern
                              let id = ''
                              let uploadUrl = ''
                              let uploaData = new FormData()
                              if (uploaderProps === 'clubLogoUpload') {
                                id = context.rootGetters['clubEdit/getterHomeClubId']
                                uploadUrl = 'homeclub/putLogo/'
                            //youNeed
                                uploaData.append('file', context.state.fileSelected)
                              }
                            //youNeed
                              Vue.prototype.$axios.post(process.env.API + uploadUrl + id, uploaData, {
                                headers: {
                                  'Content-Type': undefined
                                },
                                onUploadProgress: function (progressEvent) {
                                  let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
                                  context.commit('MutationOnUploadProgress', percentCompleted)
                                }
                              })
                                .then(function (response) {
                                  if (response.status === 200) {
                                    console.log(response)
                                    context.dispatch('app/ActionUploaderDialog', false, {root: true})
                                    context.dispatch('ActionAfterFileUpload')
                                    if (context.rootGetters['language/statusCurrentLanguage'] === 'en') {
                                      Notify.create({
                                        type: 'positive',
                                        icon: 'img:statics/icons/check.svg',
                                        color: 'positive',
                                        timeout: 1000,
                                        position: 'center',
                                        message: 'Yeah. File uploaded. Great Job!'
                                      })
                                    }
                                    if (context.rootGetters['language/statusCurrentLanguage'] === 'zh') {
                                      Notify.create({
                                        type: 'positive',
                                        icon: 'img:statics/icons/check.svg',
                                        color: 'positive',
                                        timeout: 1000,
                                        position: 'center',
                                        message: 'Yeah. File uploaded. Great Job! -ZH'
                                      })
                                    }
                                  }
                                })
                                .catch(function (error) {
                                  console.log(error)
                                })
                            }
                            

                            I think there’s a lot of stuff you won’t need but I didn’t want to tear it up. This solution enables me to use axios’s features, which are for me are a bit easier to handle.

                            I’ve prefixed the essential parts I assume you need with //youNeed

                            If there is anyone who might have an idea to improve this solution, I’d be appreciated

                            Hi… that doesn’t work… when I try formData.append it goes empty to backend… There is problem on this method. I think because of security reason it is not appendable… How did you run it?

                            1 Reply Last reply Reply Quote 0
                            • First post
                              Last post