天天看點

Django後端分離 使用element-ui檔案上傳方式

1:導入element

<!-- 引入樣式 -- 
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" rel="external nofollow"  
  <!-- 引入元件庫 -- 
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js" </script 
  <!-- 引入Vue -- 
  <script src="https://unpkg.com/element-ui/lib/index.js" </script            

複制

2:前端檔案

css:
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
 }
 .avatar-uploader .el-upload:hover {
  border-color: #409EFF;
 }
 .avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
 }
 .avatar {
  width: 178px;
  height: 178px;
  display: block;
 }

html:
  {% comment %}   上傳圖檔  {% endcomment %}
  <div id="profile" 
    <h1 style="text-align: center"  更新社團封面</h1 
    <div id="app" style="text-align: center" 
      <el-upload            :data= "datas"              // 攜帶的參數            :headers="headers"          // 請求頭
          name="image"             {% comment %}  後端接收的參數名   {% endcomment %}
          class="avatar-uploader"
          action="/show/images/"         {% comment %}  上傳路由位址  {% endcomment %}
          :show-file-list="false"
          :on-success="handleAvatarSuccess"   {% comment %} 檔案上傳成功時的鈎子 {% endcomment %}
          :before-upload="beforeAvatarUpload"  {% comment %} 上傳檔案之前的鈎子,參數為上傳的檔案 {% endcomment %}
        <img v-if="imageUrl" :src="imageUrl" class="avatar" 
        <i v-else class="el-icon-plus avatar-uploader-icon" </i 
      </el-upload 
    </div 
    
  </div 
  {% comment %}   上傳圖檔  {% endcomment %}

# JS:
<script 
  var Main = {
    data() {
      return {          headers:{},   // 請求頭是個對象          datas:{},    // 對象
        imageUrl: ''
      };
    },    create(){
          this.headers.authenticate = sessionStorage.getItem('token')  // 設定請求頭帶token
          this.datas.data = "userHead"  // 設定請求參數
    }    
    methods: {
      handleAvatarSuccess(res, file) {

        this.imageUrl = URL.createObjectURL(file.raw);
        console.log("imageUrl",this.imageUrl)
      },

      beforeAvatarUpload(file) {
        const isJPG = file.type === 'image/jpeg';
        const isLt2M = file.size / 1024 / 1024 < 2;

        if (!isJPG) {
          this.$message.error('上傳頭像圖檔隻能是 JPG 格式!');
        }
        if (!isLt2M) {
          this.$message.error('上傳頭像圖檔大小不能超過 2MB!');
        }
        return isJPG && isLt2M;
      }
    }
  }
  var Ctor = Vue.extend(Main)
  new Ctor().$mount('#app')

</script            

複制

3:後端檔案

路由:
# 預覽圖檔url("show/images/$", add_image.Image.as_view()),
py檔案:from rest_framework.views import APIView
from SocietyPlat import settings
from django.shortcuts import render, redirect, HttpResponse
from Databases import models
from django.http import JsonResponse
import os

# 擷取相對路徑
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

class Image(APIView):
  def post(self, request):

    # 接收檔案
    file_obj = request.FILES.get('image',None)     style = requetst.data.get('data')
    # 使用者名
    # username = str(request.data.get("username"))
    username = "Wang"

    print("file_obj",file_obj.name)

    # 判斷是否存在檔案夾
    head_path = BASE_DIR + "\media\{}\head".format(username).replace(" ","")
    print("head_path",head_path)
    # 如果沒有就建立檔案路徑
    if not os.path.exists(head_path):
      os.makedirs(head_path)

    # print("檔案名",file_obj.name)      # 檔案名 name.png
    #
    # print("檔案二進制",file_obj.read())   # 檔案二進制 b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x0
    #
    # print("判斷檔案  2.5M",file_obj.multiple_chunks(chunk_size=None)) # 檔案大小 False小于2.5M
    #
    # print("檔案大小",file_obj.size)    # 檔案大小 12651
    #
    # print("檔案編碼",file_obj.charset)   # None
    #
    # print("随檔案一起上傳的内容類型标題",file_obj.content_type)  # image/png
    #
    # print("包含傳遞給content-type标頭的額外參數的字典",file_obj.content_type_extra)  # {}
    #
    # print("text/content-types提供的utf8字元集編碼",file_obj.charset)  # None
    #
    #

    # 圖檔字尾
    head_suffix = file_obj.name.split(".")[1]
    print("圖檔字尾",head_suffix) # 圖檔字尾 png

    # 儲存路徑
    file_path = head_path + "\{}".format("head." + head_suffix)
    file_path = file_path.replace(" ","")
    print("儲存路徑", file_path)  # C:\Users\user\Desktop\DownTest\media\username\head\head.png

    # 上傳圖檔
    with open(file_path, 'wb') as f:
      for chunk in file_obj.chunks():
        f.write(chunk)

    message = {}
    message['code'] = 200
    # 傳回圖檔路徑
    back_path = '\static\{}\head\{}'.format(username,"head." + head_suffix).replace(" ","")
    message['image'] =  back_path

    return JsonResponse(message)           

複制

補充知識:django背景接口處理element-ui的el-upload元件form data類型資料

對于向我這樣一隻前端和後端的雙鹹魚來說寫一個不了解的接口實在是太難受了,前端不知道在哪找資料,後端又不知道處理什麼樣的資料。

現在有這樣一個需求,我需要使用element-ui中的el-upload元件完成一個上傳檔案的功能。但是不知道是不是因為我沒有發現,我翻遍了官網都沒有找到這個元件點選上傳以後發的是什麼樣的資料請求。

終于我好像突然想起來浏覽器的開發者工具可以檢視發出的請求

于是我們可以寫這麼一個元件來一探究竟:

Django後端分離 使用element-ui檔案上傳方式

點選上傳到伺服器以後前台就會送出請求,我們就可以使用devtool看具體的請求頭等等資料,具體位置在這裡:

Django後端分離 使用element-ui檔案上傳方式

點選這個upload,找一找,我們就會發現最下面有一個file

Django後端分離 使用element-ui檔案上傳方式

這應該就是我們要上傳的檔案。可以看見它是以form data的形式上傳的。

是以我們就可以寫對應的後端接口了。

這裡給一個接口的demo

def writeFile(filePath, file):
  with open(filePath, "wb") as f:
    if file.multiple_chunks():
      for content in file.chunks():
        f.write(content)
    else:
      data=file.read() ###.decode('utf-8')
      f.write(data)

def uploadFile(request):
  if request.method == "POST": 
    fileDict = request.FILES.items()
    # 擷取上傳的檔案,如果沒有檔案,則預設為None  
    if not fileDict:
      return JsonResponse({'msg': 'no file upload'})
    for (k, v) in fileDict:
      print("dic[%s]=%s" %(k,v))
      fileData = request.FILES.getlist(k)
      for file in fileData:
        fileName = file._get_name()
        filePath = os.path.join(settings.TEMP_FILE_PATH, fileName)
        print('filepath = [%s]'%filePath)
        try:
          writeFile(filePath, file)
        except:
          return JsonResponse({'msg': 'file write failed'})
    return JsonResponse({'msg': 'success'})           

複制

另外想要在前端擷取後端傳回的請求的話可以使用on-success、on-error、on-exceed這幾個鈎子函數,具體可以在element ui的官網找到

以上這篇Django後端分離 使用element-ui檔案上傳方式就是小編分享給大家的全部内容了,希望能給大家一個參考。