一、概述
现有项目中,涉及文件上传。要求:
1. 文件必须是excel
2. 只能上传1个文件
3. 文件大小不能超过5M
二、Upload 上传
注意:ElementUI Upload 上传,需要和后端api结合才能使用。
演示环境使用django,版本为:3.1.5
新建django项目
新建django项目,项目名为upload_demo,app名为api
安装以下模块
代码语言:javascript复制Django==3.1.5
djangorestframework==3.11.1
django-cors-headers==3.5.0
以上是我环境的版本,这里不做强制要求,安装最新版本即可。
注意:django-cors-headers是用来解决跨域问题的。
修改upload_demo/settings.py
注册app
代码语言:javascript复制INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'api.apps.ApiConfig',
'rest_framework',
'corsheaders', # 注册应用cors
]
中间件增加
代码语言:javascript复制MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware', # 注册组件cors
]
最后一行增加
代码语言:javascript复制#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
# CORS_ORIGIN_WHITELIST = (
# 'http://',
# )
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
)
修改api/views.py,增加视图函数
代码语言:javascript复制from rest_framework.views import APIView
from upload_demo import settings
from django.shortcuts import render, redirect, HttpResponse
from django.http import JsonResponse
from rest_framework import status
import os
import uuid
class File(APIView):
def post(self, request):
print(request.FILES)
# 接收文件
file_obj = request.FILES.get('file', None)
print("file_obj", file_obj.name)
# 判断是否存在文件夹
head_path = os.path.join(settings.BASE_DIR,'upload')
print("head_path", head_path)
# 如果没有就创建文件路径
if not os.path.exists(head_path):
os.makedirs(head_path)
# 判断文件大小不能超过5M
if file_obj.size > 5242880:
return JsonResponse({'status': status.HTTP_403_FORBIDDEN, 'msg': '文件过大'},
status=status.HTTP_403_FORBIDDEN)
# 文件后缀
suffix = file_obj.name.split(".").pop()
print("文件后缀", suffix) # 图片后缀 png
# 判断文件后缀
suffix_list = ["xlsx","xls"]
if suffix not in suffix_list:
return JsonResponse({'status': status.HTTP_403_FORBIDDEN, 'msg': '只能选择excel文件'},
status=status.HTTP_403_FORBIDDEN)
# 重命名文件名
file_name = '%s.%s'%(uuid.uuid4(),suffix)
print("file_name",file_name)
# 储存路径
file_path = os.path.join(head_path,file_name)
print("储存路径", file_path)
# 写入文件到指定路径
with open(file_path, 'wb') as f:
for chunk in file_obj.chunks():
f.write(chunk)
data = {}
data['name'] = file_name
return JsonResponse({'status': status.HTTP_200_OK, 'data': data}, status=status.HTTP_200_OK)
修改upload_demo/urls.py
代码语言:javascript复制from django.contrib import admin
from django.urls import path
from api import views
urlpatterns = [
path('admin/', admin.site.urls),
path('file/excel_upload/',views.File.as_view())
]
启动django项目,访问链接为:http://127.0.0.1:8000/
新建vue测试页
安装axios
代码语言:javascript复制npm install axios --save
test.vue
代码语言:javascript复制<template>
<div style="width: 70%;margin-left: 30px;margin-top: 30px;">
<el-upload ref="upload"
class="upload-demo" :multiple='false' :auto-upload='true' list-type='text' :show-file-list='true'
:before-upload="beforeUpload" :before-remove="beforeRemove" :drag='true' action='' :limit="1" :on-exceed="handleExceed"
:http-request="uploadFile" accept=".xlsx" >
<i class="el-icon-upload"></i>
<div class="el-upload__text"><em>点击上传,仅限excel文件</em></div>
<!-- <div class="el-upload__tip" slot="tip">仅限excel文件</div>-->
</el-upload>
<el-button type="primary" @click="onSubumit">提交</el-button>
</div>
</template>
<script>
// 导入模块
import axios from 'axios'
export default {
components: {
axios
},
data() {
return {
isUpload:false, // 是否上传文件
}
},
mounted: function() {
},
methods: {
// 上传文件之前的钩子
beforeUpload(file) {
//判断文件格式
let hz = file.name.split('.').pop()
// console.log("hz",hz)
if (hz != 'xlsx' && hz != 'xls') {
this.$message.error(`只能选择excel文件`)
return false
}
// 判断文件大小
let fileSize = file.size / 1024 / 1024 < 5
if (!fileSize) {
this.$message.error('上传文件大小不能超过 5MB')
return false
}
this.isUpload = true
},
// 删除文件之前的钩子
beforeRemove(file){
this.isUpload = false
},
// 上传文件个数超过定义的数量
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 1 个文件,请删除后继续上传`)
},
// 上传文件
uploadFile(item) {
let _this = this
let fileObj = item.file
const form = new FormData()// FormData 对象
form.append('file', fileObj)// 文件对象 'upload'是后台接收的参数名
axios({
url: 'http://127.0.0.1:8000/file/excel_upload/',
data: form,
method: 'POST',
contentType: 'multipart/form-data',
processData: false //告诉jquery不要对form进行处理
// contentType: false, //指定为false才能形成正确的Content-Type
})
.then(function(res) {
// console.log('上传成功', res)
// console.log("上传路径",res.data.excel_file_path)
_this.$message.success("上传成功")
})
.catch(function(err) {
let res = err.response
// console.log('失败', res)
_this.$message.error(res.data.msg)
})
},
// 检查是否上传
onSubumit(){
if (this.isUpload == false){
this.$message.error("请上传excel文件")
return false
} else {
this.$message.success("文件已上传")
return true
}
},
}
}
</script>
<style>
</style>
请自行修改路由
访问vue测试页,效果如下:
上传非excel文件,效果如下:
上传大于5M的excel文件,效果如下:
上传正确的excel文件,效果如下:
查看接口返回信息,效果如下:
查看django项目的upload目录,就可以看到上传的文件了。