前言:
此时各位老铁们对“ie formdata 未定义”大体比较关怀,咱们都想要剖析一些“ie formdata 未定义”的相关内容。那么小编同时在网摘上收集了一些关于“ie formdata 未定义””的相关资讯,希望兄弟们能喜欢,大家一起来了解一下吧!文件上传1.环境
前端
Vue3
PrimeVUE
后端
Python
FastAPI
2.文件存储
在软件开发中,上传文件是经常会使用到的一个功能,那么文件存储也就变得非常重要起来了。在以往的小项目中,文件存储都是在直接在磁盘上存储的,但这样的方式,随着微服务的发展,部署在不同机器上的微服务之间需要共享数据,直接存储在磁盘上的文件就不方便文件共享了。鉴于此,我们在开发相对较大的软件时,就需要将文件存储在数据库或者分布式文件系统中,在此,我们选择了MongoDB的GridFS来存储文件,也就是说在文件上传时将文件存储到MongoDB数据库中,然后接口返回文件的OID。
3.文件上传方式
文件上传一般的方式是需要支持单文件上传和多文件上传的,但本质上来讲是一回事,所以在设计文件上传接口时,我们将文件上传统一为一个接口,支持多个文件上传即可。
4.后端文件上传源代码
# coding: utf-8import settingsfrom logger import loggerfrom api.upload import routerfrom fastapi import Filefrom fastapi import Dependsfrom fastapi import UploadFilefrom typing import Listfrom pymongo import MongoClientfrom gridfs import GridFSfrom common.common import find_current_usr@router.post(path='/upload_files')async def upload_files(files: List[UploadFile] = File(...), current_usr: dict = Depends(find_current_usr)): res = {'res': False, 'oids': []} with MongoClient(settings.MONGO_HOST, settings.MONGO_PORT) as connect: filedb = connect.filedb mgfs = GridFS(filedb) for file in files: # 写入gridfs logger.log('Upload file {0} from {1}'.format(file.filename, current_usr['name'])) dic = dict() dic['filename'] = file.filename oid = mgfs.put(await file.read(), **dic) res['oids'].append(str(oid)) res['res'] = True return res
通过以上源代码,我们可以看到:接口接收在表单中传递的 files 参数,files 类型为列表,然后对接收到的文件循环写入 MongoDB,最后返回 MongoDB 的文件 OID 列表。返回值:
{'res': False, 'oids': []}
其中:res 表示是否上传成功,oids 表示 MongoDB 文件 OID 列表。
5.前端文件上传封装
由于后端接收的是文件,而不是普通的数据,所以前端在传输数据时必须以表单的形式传递,也就是说,请求头中必须指定:
'Content-Type': 'multipart/form-data'
另外由于在上传文件时需要携带令牌,所以,需要对上传文件的 js 代码进行封装,代码如下:
function errorToString (error) { let text = '' if (error.response.data) { if (error.response.data instanceof Object) text = JSON.stringify(error.response.data) else text = error.response.data } return text}// 文件上传const fileConfig = { baseURL: '', timeout: 60000, headers: { 'Content-Type': 'multipart/form-data' }, responseType: 'json'}// 携带令牌的文件上传const uploadRequest = (url, data) => { let _id = loading() // eslint-disable-next-line const promise = new Promise((resolve, reject) => { fileConfig.headers['Authorization'] = localStorage.getItem('token_type') + ' ' + localStorage.getItem('access_token') axios.post( url, data, fileConfig ).then((response) => { loaded(_id) resolve(response) }).catch((error) => { loaded(_id) console.log(error) // 对error中的数据进行处理 let status = error.response.status let txt = errorToString(error) // 弹出错误信息 if (status === 401) { swal({ title: status.toString(), text: txt, icon: 'error', button: "确定", }).then((value) => { console.log(value) window.top.location.href = '/index.html' }) } else { swal(status.toString(), txt, 'error') } // reject(error) }) }) return promise}
这样经过封装后,前端在上传文件时,只需要调用 uploadRequest 函数就可以完成文件的上传,调用格式:
uploadRequest( '/qycommon_api/upload/upload_files', formData ).then((response) => { if (response.data.res) { ...... } else { ...... } })
在上面的代码中,我们看到 formData 这个变量,那么下面我们来说明一下前端上传文件的方法。
6.前端上传文件代码
前端上传文件,我们采用 PrimeVUE 的 upload 组件,该组件实际上是一个三态组件,包括:选择文件、上传文件、取消文件。但我们在一般的使用中,希望做到直接选择文件后就上传,同时获取到上传文件的 OID ,然后将 OID 记录到数据表中。实现代码如下:
组件
<FileUpload name="demo[]" mode="basic" accept="image/*" chooseLabel="更换" :auto="true" @select="upload_avatar_file"/>
事件
upload_avatar_file (event) { var formData = new FormData() event.files.forEach((file) => { formData.append('files', file) }) let _this = this uploadRequest( '/qycommon_api/upload/upload_files', formData ).then((response) => { if (response.data.res) { swal({title: "提示!", text: "操作成功!", icon: "success", button: false, timer: 1000}) _this.download_avatar_file(response.data.oids[0]) // 下载文件 _this.write_my_avatar(response.data.oids[0]) // 将文件的 OID 写入数据表 } else { swal({title: "提示!", text: "操作失败!", icon: "error", button: false, timer: 1000}) } }) },
说明:
1.select 事件
在组件中,我们使用了 select 事件来上传文件,而不是 uploader 事件,同时将 auto 设置为 true,表示使用自动上传。这样会在上传文件时出现错误,因为我们没有指定组件的 url ,但不会有问题,因为我们在选择文件时已经将文件上传了。只是在浏览器的调试环境中可以看到请求了一个 null 的错误。
2.FormData
在自定义的文件上传中,我们使用了 FormData ,循环将文件写入 FormData 的 files 中。
标签: #ie formdata 未定义 #前端传文件给后端用什么格式