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>