Vue.js 来自axios的Quasar上载文件

Vue.js 来自axios的Quasar上载文件,vue.js,vuejs2,vue-component,quasar-framework,quasar,Vue.js,Vuejs2,Vue Component,Quasar Framework,Quasar,我有一个包含多个输入的表单,其中也包含文件输入。现在,我想通过onSubmit函数传递这些数据。但是,有一个问题,在quasar文档中,我没有在脚本部分看到关于Axios上传文件的说明。 我读过,也读过这本书,但我没有为自己工作 另外,这是我的模板代码: <template> <div class="q-pa-md q-mt-md"> <q-card class="my-card"> <q-form @submit

我有一个包含多个输入的表单,其中也包含文件输入。现在,我想通过
onSubmit
函数传递这些数据。但是,有一个问题,在quasar文档中,我没有在脚本部分看到关于Axios上传文件的说明。 我读过,也读过这本书,但我没有为自己工作

另外,这是我的模板代码:

<template>
  <div class="q-pa-md q-mt-md">
    <q-card class="my-card">
      <q-form
        @submit="onSubmit"
        class="q-gutter-md"
      >
        <div class="row justify-center">
          <q-uploader
            label="Upload your music"
            color="purple"
            accept=".mp3"
            :max-file-size="20000000"
            square
            flat
            @add="file_selected"
            bordered
          />
        </div>
        <div class="row justify-center">
          <q-btn label="Edit" type="submit" color="primary" v-if="song_id" class="q-ma-md" />
          <q-btn label="Add" type="submit" color="primary" v-else class="q-ma-md" />
          <q-btn label="Cancel" type="reset" color="primary" flat class="q-ml-sm" />
        </div>
      </q-form>
    </q-card>
  </div>
</template>
数据
部分:

data: () => ({
    selected_file: '',
    check_if_document_upload: false,
    song_id: '',
    song_data: {
      status: true
    },
    dashData: []
  }),

如果quasar uploads不适用于您,并且您正在使用状态管理vuex,那么您可以尝试编写自定义代码来完成您想要的任务。尝试使用axios发送post请求

createEvents({ commit }, payload) {
  const stuff = {
    title: payload.title,
    location: payload.location,
    description: payload.description,
    image = payload.image;
  };
  let formData = new FormData();
  bodyFormData.set('title', stuff.title); //done for the text data
  formData.append("imageUrl", stuff.image);  //done for file data

  axios
    .post({
        method: 'post',
        url: 'myurl',
        data: formData,
         headers: {'Content-Type': 'multipart/form-data' }
     })
    .then(response => {
      commit("createEvents", response.data);
    })
    .catch(err => err.data);
  }
 }
对于submit函数(方法),它应该如下所示

createEvent(){
      const newEvent = {
        title: '',
        location: '',
        description: '',
        image: this.image,
      };
      this.$store.dispatch("createEvents", newEvent);
    };
最后,表单本身在代码中。应使用简单的
表单的其余部分可以正常使用

<form>
  <input type='text' v-model='text'>
  <-- more of the same -->
  <input type='file' ref='image'>
  <button type=submit @click.prevent=createEvent()>submit</button> //prevent is to keep the page from reloading when the form gets submitted, just a precaution measure
</form>

submit//prevent是为了防止表单提交时页面重新加载,这只是一种预防措施

希望这有帮助

我发现了我的问题。我应该将模板中的
@add
更改为
@added

<template>
  <div class="q-pa-md q-mt-md">
    <q-card class="my-card">
      <q-form
        @submit="onSubmit"
        class="q-gutter-md"
      >
        <div class="row justify-center">
          <q-uploader
            label="Upload your music"
            color="purple"
            accept=".mp3"
            :max-file-size="20000000"
            square
            flat
            @added="file_selected"
            bordered
          />
        </div>
        <div class="row justify-center">
          <q-btn label="Edit" type="submit" color="primary" v-if="song_id" class="q-ma-md" />
          <q-btn label="Add" type="submit" color="primary" v-else class="q-ma-md" />
          <q-btn label="Cancel" type="reset" color="primary" flat class="q-ml-sm" />
        </div>
      </q-form>
    </q-card>
  </div>
</template>

如果你想保留QUploader功能、状态更改、上传进度,在我的例子中,我做了组件扩展,它工作正常,可能它没有效率,因为我必须添加自己的方法:上传、上传文件

不要添加方法来覆盖_runFactory,因为我省略了批处理加载选项,并且我将始终使用factory作为函数

qploader来源:

上传(){
if(this.canUpload===false){
返回
}
const queue=this.queuedFiles.slice(0)
this.queuedFiles=[]
if(此.xhrops.batch(队列)){
此.\uu运行工厂(队列)
}
否则{
queue.forEach(文件=>{
此.\uu运行工厂([文件])
})
}
},
__运行工厂(文件){
这是一本书++
if(this.factory的类型!=“函数”){
这个。uu上传文件(文件,{})
返回
}
const res=this.factory(文件)
如果(!res){
这是$emit(
“工厂倒闭”,
新错误('QUploader:factory()未正确返回'),
文件夹
)
这是一本书--
}
else if(typeof res.catch==='function'&&typeof res.then=='function'){
这个。承诺。推动(res)
常量失败=错误=>{
如果(此.\u正在销毁!==true&&this.\u已销毁!==true){
this.promissions=this.promissions.filter(p=>p!==res)
if(this.promissions.length==0){
this.abortPromises=false
}
this.queuedFiles=this.queuedFiles.concat(文件)
files.forEach(f=>{this.\u updateFile(f,'failed')})
此.$emit('factory-failed',err,files)
这是一本书--
}
}
res.then(工厂=>{
if(this.abortPromises===true){
失败(新错误('Aborted'))
}
否则,如果(此.\u正在销毁!==true&&this.\u已销毁!==true){
this.promissions=this.promissions.filter(p=>p!==res)
这是上传文件(文件,工厂)
}
}).catch(失败)
}
否则{
这个.uu上传文件(文件,res | |{})
}
},
__上载文件(文件、工厂){
常数
form=新FormData(),
xhr=新的XMLHttpRequest()
const getProp=(名称,arg)=>{
返回工厂[名称]!==无效0
?getFn(工厂[名称])(参数)
:this.xhrops[name](arg)
}
const url=getProp('url',文件)
如果(!url){
控制台。错误('q-uploader:无效或未指定URL')
这是一本书--
返回
}
const fields=getProp('formFields',files)
字段!==void 0&&fields.forEach(字段=>{
form.append(field.name、field.value)
})
让
uploadIndex=0,
uploadIndexSize=0,
uploadedSize=0,
maxUploadSize=0,
流产
xhr.upload.addEventListener('progress',e=>{
如果(中止===true){return}
const load=Math.min(maxUploadSize,e.loaded)
this.uploadedSize+=已加载-uploadedSize
uploadedSize=已加载
let size=uploadedSize-uploadIndexSize
对于(让i=uploadIndex;size>0&&i文件大小
如果(上传){
size-=file.size
上传索引++
uploadIndexSize+=file.size
此.\uuuuUpdateFile(文件“上载”,文件.size)
}
否则{
此.\uuu更新文件(文件“上载”,大小)
返回
}
}
},错)
xhr.onreadystatechange=()=>{
如果(xhr.readyState<4){
返回
}
如果(xhr.status&&xhr.status<400){
this.uploadedFiles=this.uploadedFiles.concat(文件)
files.forEach(f=>{this.\u updateFile(f,'uploaded')})
此.$emit('upload',{files,xhr})
}
否则{
中止=真
this.uploadedSize-=uploadedSize
this.queuedFiles=this.queuedFiles.concat(文件)
files.forEach(f=>{this.\u updateFile(f,'failed')})
此.$emit('failed',{files,xhr})
}
这是一本书--
this.xhrs=this.xhrs.filter(x=>x!==xhr)
}
xhr.open(
getProp('方法',文件),
网址
)
if(getProp('withCredentials',files)==true){
xhr.withCredentials=true
}
const headers=getProp('headers',files)
headers!==void 0&&headers.forEach(head=>{
setRequestHeader(head.name,head.value)
})
const sendRaw=getProp('sendRaw',files)
files.forEach(文件=>{
此.\uuuu更新文件(文件“正在上载”,0)
如果(sendRaw!==true){
append(getProp('fieldName',file),file,file.name)
}
file.xhr=xhr
文件。uu abort=()=>{xhr.abort()}
maxUploadSize+=file.size
})
此.$emit('uploading',{files,xhr})
此.xhr.push(xhr)
如果(sendRaw==真){
发送(新Blob(文件))
}
否则{
xhr.send(表格)
}
}
结果:使用AXIOS组件Vue
<template>
  <div class="q-pa-md q-mt-md">
    <q-card class="my-card">
      <q-form
        @submit="onSubmit"
        class="q-gutter-md"
      >
        <div class="row justify-center">
          <q-uploader
            label="Upload your music"
            color="purple"
            accept=".mp3"
            :max-file-size="20000000"
            square
            flat
            @added="file_selected"
            bordered
          />
        </div>
        <div class="row justify-center">
          <q-btn label="Edit" type="submit" color="primary" v-if="song_id" class="q-ma-md" />
          <q-btn label="Add" type="submit" color="primary" v-else class="q-ma-md" />
          <q-btn label="Cancel" type="reset" color="primary" flat class="q-ml-sm" />
        </div>
      </q-form>
    </q-card>
  </div>
</template>
 upload () {
  if (this.canUpload === false) {
    return
  }

  const queue = this.queuedFiles.slice(0)
  this.queuedFiles = []

  if (this.xhrProps.batch(queue)) {
    this.__runFactory(queue)
  }
  else {
    queue.forEach(file => {
      this.__runFactory([ file ])
    })
  }
},

__runFactory (files) {
  this.workingThreads++

  if (typeof this.factory !== 'function') {
    this.__uploadFiles(files, {})
    return
  }

  const res = this.factory(files)

  if (!res) {
    this.$emit(
      'factory-failed',
      new Error('QUploader: factory() does not return properly'),
      files
    )
    this.workingThreads--
  }
  else if (typeof res.catch === 'function' && typeof res.then === 'function') {
    this.promises.push(res)

    const failed = err => {
      if (this._isBeingDestroyed !== true && this._isDestroyed !== true) {
        this.promises = this.promises.filter(p => p !== res)

        if (this.promises.length === 0) {
          this.abortPromises = false
        }

        this.queuedFiles = this.queuedFiles.concat(files)
        files.forEach(f => { this.__updateFile(f, 'failed') })

        this.$emit('factory-failed', err, files)
        this.workingThreads--
      }
    }

    res.then(factory => {
      if (this.abortPromises === true) {
        failed(new Error('Aborted'))
      }
      else if (this._isBeingDestroyed !== true && this._isDestroyed !== true) {
        this.promises = this.promises.filter(p => p !== res)
        this.__uploadFiles(files, factory)
      }
    }).catch(failed)
  }
  else {
    this.__uploadFiles(files, res || {})
  }
},

__uploadFiles (files, factory) {
  const
    form = new FormData(),
    xhr = new XMLHttpRequest()

  const getProp = (name, arg) => {
    return factory[name] !== void 0
      ? getFn(factory[name])(arg)
      : this.xhrProps[name](arg)
  }

  const url = getProp('url', files)

  if (!url) {
    console.error('q-uploader: invalid or no URL specified')
    this.workingThreads--
    return
  }

  const fields = getProp('formFields', files)
  fields !== void 0 && fields.forEach(field => {
    form.append(field.name, field.value)
  })

  let
    uploadIndex = 0,
    uploadIndexSize = 0,
    uploadedSize = 0,
    maxUploadSize = 0,
    aborted

  xhr.upload.addEventListener('progress', e => {
    if (aborted === true) { return }

    const loaded = Math.min(maxUploadSize, e.loaded)

    this.uploadedSize += loaded - uploadedSize
    uploadedSize = loaded

    let size = uploadedSize - uploadIndexSize
    for (let i = uploadIndex; size > 0 && i < files.length; i++) {
      const
        file = files[i],
        uploaded = size > file.size

      if (uploaded) {
        size -= file.size
        uploadIndex++
        uploadIndexSize += file.size
        this.__updateFile(file, 'uploading', file.size)
      }
      else {
        this.__updateFile(file, 'uploading', size)
        return
      }
    }
  }, false)

  xhr.onreadystatechange = () => {
    if (xhr.readyState < 4) {
      return
    }

    if (xhr.status && xhr.status < 400) {
      this.uploadedFiles = this.uploadedFiles.concat(files)
      files.forEach(f => { this.__updateFile(f, 'uploaded') })
      this.$emit('uploaded', { files, xhr })
    }
    else {
      aborted = true
      this.uploadedSize -= uploadedSize
      this.queuedFiles = this.queuedFiles.concat(files)
      files.forEach(f => { this.__updateFile(f, 'failed') })
      this.$emit('failed', { files, xhr })
    }

    this.workingThreads--
    this.xhrs = this.xhrs.filter(x => x !== xhr)
  }

  xhr.open(
    getProp('method', files),
    url
  )

  if (getProp('withCredentials', files) === true) {
    xhr.withCredentials = true
  }

  const headers = getProp('headers', files)
  headers !== void 0 && headers.forEach(head => {
    xhr.setRequestHeader(head.name, head.value)
  })

  const sendRaw = getProp('sendRaw', files)

  files.forEach(file => {
    this.__updateFile(file, 'uploading', 0)
    if (sendRaw !== true) {
      form.append(getProp('fieldName', file), file, file.name)
    }
    file.xhr = xhr
    file.__abort = () => { xhr.abort() }
    maxUploadSize += file.size
  })

  this.$emit('uploading', { files, xhr })
  this.xhrs.push(xhr)

  if (sendRaw === true) {
    xhr.send(new Blob(files))
  }
  else {
    xhr.send(form)
  }
}
    <script lang="ts">
import { QUploader } from 'quasar';

export default class AxiosUploader extends QUploader {
  constructor(props) {
    super(props);
  }


  AxiosUpload() {
    if (this.canUpload === false) {
      return;
    }

    const queue = this.queuedFiles.slice(0);
    this.queuedFiles = [];

    const factory = this.factory(queue);


    queue.forEach(file => {
      this.workingThreads++;
      this.uploadFiles([file], factory);
    });
  }

  uploadFiles(files, factory) {
    const form = new FormData(),
      headers = {};

    factory.headers.forEach(head => {
      headers[head.name] = head.value;
    });


    factory.formFields.forEach(field => {
      form.append(field.name, field.value);
    });

    form.append(factory.fieldName, files[0], files[0].name);

    let uploadIndex = 0,
      uploadIndexSize = 0,
      uploadedSize = 0,
      maxUploadSize = 0,
      aborted;


    const xhr = this.$axios.post(factory.url, form, {
      headers,
      onUploadProgress: (e: ProgressEvent) => {
        if (aborted === true) {
          return;
        }
        const loaded = Math.min(maxUploadSize, e.loaded);

        this.uploadedSize += loaded - uploadedSize;
        uploadedSize = loaded;

        let size = uploadedSize - uploadIndexSize;
        for (let i = uploadIndex; size > 0 && i < files.length; i++) {
          const file = files[i],
            uploaded = size > file.size;

          if (uploaded) {
            size -= file.size;
            uploadIndex++;
            uploadIndexSize += file.size;
            this.__updateFile(file, 'uploading', file.size);
          } else {
            this.__updateFile(file, 'uploading', size);
            return;
          }
        }
      }
    });

    this.xhrs.push(xhr);
    this.$emit('uploading', { files, xhr });

    xhr
      .then(res => {
        this.uploadedFiles = this.uploadedFiles.concat(files);
        files.forEach(f => {
          this.__updateFile(f, 'uploaded');
        });
        this.$emit('uploaded', { files, xhr });
      })
      .catch(err => {
        aborted = true;
        this.uploadedSize -= uploadedSize;
        this.queuedFiles = this.queuedFiles.concat(files);
        files.forEach(f => {
          this.__updateFile(f, 'failed');
        });
        this.$emit('failed', { files, xhr });
      })
      .finally(() => {
        this.workingThreads--;
        this.xhrs = this.xhrs.filter(x => x !== xhr);
      });

    files.forEach(file => {
      this.__updateFile(file, 'uploading', 0);
      file.xhr = xhr;
      file.__abort = () => {
        xhr.abort();
      };
      maxUploadSize += file.size;
    });

    this.$emit('uploading', { files, xhr });
    this.xhrs.push(xhr);

  }
}
</script>