很久没有更新博客了,由于最近在做ResNet 的图像分类和定位相关,但是还没有很大的收获,因此暂缓更新。因为一些原因需要做上传的功能,所以就有了这篇博文了。
目的:网页端文件上传
计划:A:使用Flask 框架 B:使用PHP C:使用Fastapi
计划选用:C
原因:首先就tiny项目而言,越简单越好,如奥卡姆剃须刀原理所讲“如无必要,勿增实体”,也像是某水果公司的“旧”理念——“至繁归于至简”。其次Fastapi 的效率也相对Python的Flask 高一些,不采用PHP是因为这个“世界上最好的语言”局限性太强,虽然有其优点,但是它就像是满嘴繁文缛节的老学究。
步骤分析:创建一个file类型的输入框并隐藏起来,创建两个按钮,一个按钮添加文件,另外一个按钮点击后开始上传。
在我看来,使用Vue 的js比配置Vue环境更简单,因此web端直接使用原生html5即可。代码如下:
<!DOCTYPE html><html><head><meta charset=”UTF-8″><link rel=”stylesheet” href=”https://unpkg.com/element-ui/lib/theme-chalk/index.css”></head><body><div id=”app”><el-button @click=”addFile”>addFile</el-button><el-button @click=”uploadFile”>uploadFile</el-button><input type=”file” ref=”upload_input” style=”display: none;” @change=”select_file”></div></body><script src=”https://unpkg.com/vue/dist/vue.js”></script><script src=”https://unpkg.com/element-ui/lib/index.js”></script><script src=”https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js”></script><script>new Vue({el: ‘#app’,data: function () {return {select_file_data: ”,target_url: ‘http://127.0.0.1:8000/upload’ //上传文件的目标地址,即后台运行的暴露地址}},methods: {addFile: function () {this.$refs.upload_input.click() //通过ref模拟点击},uploadFile: function () {let uploads = new FormData() //创建FormDatalet config = { headers: { “Content-Type”: “multipart/form-data” } }if (this.select_file_data != “”) {uploads.append(“file”,this.select_file_data[0]) //此处只展示上传单个文件axios.post(this.target_url, uploads, config).then(function (res) {console.log(res.data)})}},select_file: function (file) {this.select_file_data = file.target.filesconsole.log(this.select_file_data)}}})</script></html>
注:其实看了上面代码的小朋友已经发现了我使用了Element-UI ,其实Element官方提供了上传文件的控件,由于代码需要,我并没有直接引用他们的组件。
服务端代码:
# -*-coding:utf-8-*-from fastapi import FastAPI, UploadFile,File #Fastapifrom fastapi.middleware.cors import CORSMiddleware #跨域调用import uvicornapp = FastAPI()origins = [“*”]# 或者[“http://wicos.me”] 可以自定义允许访问的地址app.add_middleware(CORSMiddleware,allow_origins=origins,allow_credentials=True,allow_methods=[“*”],allow_headers=[“*”],)@app.post(“/upload”)async def recv_file(file: UploadFile = File(…)):file_data = await file.read()with open(file.filename,”wb”) as fp:fp.write(file_data)fp.close()rt_msg = {“name”: file.filename,“type”: file.content_type}return rt_msg
服务端接收文件其实主要是Fastapi 的File 和 UploadFile 两个功能,官方在上传文件方面给了两个实例如下,
我们主要选择使用UploadFile 其二者的区别在于Upload File可以将上传的文件储存在“本地”而不是内存中,对于一些视频,压缩包此类大文件很友好。
其次,Upload File有三个属性和四个async方法:
属性:
- filename:文件名
- content_type:文件类型
- file:返回SpooledTemporaryFile类型文件
四个方法:
- read(N):默认读所有的字节,或者read(N) 读入N个字节/字符
- write (data):将data写入文件
- seek(offset):转到文件中的某个字节位置offset(int)
- close():关闭文件
后台再启动服务
uvicorn test:main –reload #test代表后端文件名
以上就是一个简单的上传样例,我已上传到我的GayHub(github)了:https://github.com/Pidbid/vue-fastapi-sample