由于项目展示信息有图片,需要自己实现文件上传,通过django+vue+element-ui,实现文件上传服务+上传表单
*注: 因为是内部使用的项目(使用人数<100),不需要考虑高并发等情况,所以一切从简。不适合大型项目
一、前端部分
前端组件用的element-ui,使用el-upload,因为是表单,所以外层用了el-form
<el-form ref="editForm" :model="editForm" :ruels="editFormRules">
<el-form-item
label="获奖年份"
prop="awardYear"
>
<el-input-number
v-model="editForm.awardYear"
:min="1"
label="描述文字"
size="small"
/>
</el-form-item>
<el-form-item label="展示图片" prop="awardPic">
<div style="display:flex">
<el-upload
v-model="editForm.awardPic"
drag
:action="actionUrl"
:on-success="editSuccess"
multiple
>
<i class="el-icon-upload" />
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div
slot="tip"
class="el-upload__tip"
>只能上传jpg/png/jpeg文件,且不超过2M</div>
<div
slot="tip"
class="el-upload__tip"
style="line-height: 20px"
>建议图片尺寸1600x1200 或 1200X1200,否则展示效果可能不佳</div>
</el-upload>
<el-image :src="editForm.awardPic" style="width: 150px; height: 150px" /> //展示上传的图片
</div>
</el-form-item>
<div style="display: flex;flex-wrap: nowrap;justify-content: center;margin-top:40px">
<el-button type="primary" @click="editFormSubmit()">提交</el-button>
<el-button type="">取消</el-button>
</div>
</el-form>
这里展示图片没用用el-upload的样例,官方文档里面有图片墙,但是感觉不用那么麻烦
el-upload使用时,只要选择了图片,基本都会在前端显示上传成功,即使后端上传失败了。所以需要通过onSuccess 属性获取后端的返回结果(只要请求成功即可,不需要后端上传成功)。
这里有一个el-form的坑,el-form的表单校验需要用的rules属性,而el-upload是不需要v-model的,为了格式统一,为其添加了v-model,注意prop的值和v-model绑定的值一定要名称相同,不然无法校验!!
js部分
export default {
data() {
return {
// 编辑
actionUrl: + 'http://localhost:8002/api/v1/upload', //上传文件的后端接口url,不需要传参(组件会把FILE放到参数中)
editFormRules: {
awardYear: [
{ required: true, message: '请输入获奖年份', trigger: 'blur' }
],
awardPic: [
{ required: true, message: '请上传获奖图片', trigger: 'blur' }
]
},
editForm: {},
}
},
method(){
editFormSubmit() {
// 编辑内容后提交
this.$refs['editForm'].validate((valid) => {
if (valid) {
apiEditData(this.editForm).then((res) => { //apiEditData是向后端提交表单的接口
if (res.code === 0) {
this.$message({ message: res.msg, type: 'success' })
this.initTable()
} else {
this.$message({ message: res.msg, type: 'error' })
}
})
} else {
return false
}
})
},
editSuccess(response, file, fileList) {
console.log(response)
if (response.code === 0) {
this.$message.success('文件上传成功!url=' + response.awardPic)
this.editForm.awardPic = response.awardPic //赋值后可以在右侧显示成功上传的图像(编辑时也可以这样操作)
} else {
this.$message.error('上传图片失败')
}
},}
二、后端部分
项目中需要展示上传的图片,有两种办法
1.将图片放在前端。将图片放在vue项目的public目录下,前端直接访问
<el-image src="./xxxx.jpg" />
因为public文件夹的静态资源都会被简单赋值,不经过webpack。通过绝对路径引用即可。不过并不建议这样,因为图像文件的数量会很多,而且从这里引用的动态绑定效果很差。
2.将图片上传到文件服务器,保存文件地址,这样引用图像地址即可
<el-image :src="edltForm.imageUrl" />
由于没有文件服务器,所以想到了另外一个简单的办法。
我们知道Django服务的settings.STATICFILES_DIRS 是静态文件目录,如果将文件放在该目录下,只需要访http://{host}/static/xxx.jpg就可以直接访问静态资源。所以可以写一个简单的django文件服务。项目结构如下
SIMPLE_FTP
│ db.sqlite3
│ manage.py
│
├─SIMPLE_FTP
│ │ asgi.py
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│
├─static
│ │ __init__.py
│ └─imgData
├─upload
│ │ admin.py
│ │ apps.py
│ │ form.py
│ │ models.py
│ │ tests.py
│ │ views.py
│ │ __init__.py
这里用最基本的django项目就行了,参考Django中文文档的第一章
这里我们选择通过模型上传
/SIMPLE_FTP/upload/models.py
from django.db import models
class UploadFileField(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField('文件名', max_length=200)
file = models.FileField(upload_to='imgDir') # 文件会保存到{STATICFILES_DIRS}/imgDir目录下
updateTime = models.DateTimeField('更新日期', auto_now=True)
filePath = models.CharField('文件地址', max_length=200)
class Meta:
db_table = 'config_upload_model'
/SIMPLE_FTP/upload/views.py
import os
import datetime
from django.views import View
from django.http import JsonResponse
from upload.models import UploadFileField
from SIMPLE_FTP.settings import STATICFILES_DIRS
class UploadFile(View):
"""文件上传"""
def post(self, request):
print('>>>开始文件上传<<<')
try:
mf = UploadFileField()
file_ = request.FILES['file']
mf.title = file_.name
mf.file = file_
oriFilePath = os.path.join(STATICFILES_DIRS, 'my_project', file_.name)
oriFileName = file_.name.rsplit('.', 1)[0]
oriFileType = file_.name.rsplit('.', 1)[1]
newFileName = f'{oriFileName}__{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.{oriFileType}' # 添加时间戳,避免文件名重复
filePath = os.path.join(STATICFILES_DIRS, 'imgDir', newFileName)
mf.filePath = filePath
awardPic = os.path.join('http://localhost:8002', 'static', 'honor_hall', newFileName)
mf.save()
os.rename(oriFilePath, filePath) # 重命名文件,避免重复
return JsonResponse({"code": 0, "data": '上传文件成功', 'awardPic': awardPic},
json_dumps_params={'ensure_ascii': False})
except Exception as e:
print('ERROR:', e.__str__())
return JsonResponse({"code": 200, "data": '上传文件失败', 'err': e.__str__()},
json_dumps_params={'ensure_ascii': False})
/SIMPLE_FTP/SIMPLE_FTP/urls.py
# from django.contrib import admin
from django.urls import path
from django.urls import path, re_path
# from django.views.static import serve
# from SIMPLE_FTP.settings import MEDIA_ROOT
from upload.views import UploadFile, Test
urlpatterns = [
# path('admin/', admin.site.urls),
# 图片访问
# re_path(r"media/(?P<path>.*)", serve, {"document_root": MEDIA_ROOT}),
path('api/v1/upload', UploadFile.as_view(), name='upload'),
# path('api/v1/test', Test.as_view(), name='test')
]
然后启动迁移数据库,并启动SIMPLE_FTP项目
python manage.py makemigrations upload
python manage.py migrate upload
nohup python mamage.py runserver 0.0.0.0:8002 &
可以在static/imgData下面放一张图片xxx.jpg,然后访问http://localhost:8002/static/imgData/xxx.jpg,如果能够成功访问,表明启动正常。
此时启动前端项目,

选择图片并上传

注意查看控制台打印信息,SIMPLE_FTP上传成功,返回图像保存地址
{code: 0, data: '上传文件成功', awardPic: http://XXXXXX:8002/static/imgData/007hyfXLgy1g8u0alnpqhj302802874u__20220429174353.jpg'}
此时
this.editForm={awardYear:2022,awardPic:"http://XXXXXX:8002/static/imgData/007hyfXLgy1g8u0alnpqhj302802874u__20220429174353.jpg"}
点击“提交”,提交表单,后端只需要将表单数据保存即可。需要使用图像的时候,根据保存条件获取到awardPic,在前端<el-image :src="awardPic" />
使用即可
网友评论