美文网首页
el-upload + Django实现文件上传

el-upload + Django实现文件上传

作者: Cc_Leo | 来源:发表于2022-04-29 17:56 被阅读0次

由于项目展示信息有图片,需要自己实现文件上传,通过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,如果能够成功访问,表明启动正常。

此时启动前端项目,


image.png

选择图片并上传


image.png
注意查看控制台打印信息,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" />使用即可

相关文章

网友评论

      本文标题:el-upload + Django实现文件上传

      本文链接:https://www.haomeiwen.com/subject/ewpsyrtx.html