在一個網站中,上傳檔案也是相當重要的功能,諸如匯入或是更新用戶內容經常會用到。

首先,先解決CSRF跨域請求的安全機制。

方式一:

在form標籤中,加入 {% csrf_token %} 

<form id="form" action="/userinfo/" method="POST">
    {% csrf_token %}
    <div>
        <input type="text" name="username" />
    </div>
  <input type="submit" value="提交"/>
</form>

方式二:

如果使用jquery ajax提交,

<script src="/static/jquery.cookie.js" charset="utf-8"></script>
$.ajax({
        url:"/bookstore/file_put/",
        type:"POST",
        headers:{
            "X-CSRFToken":$.cookie('csrftoken')
        },
}) 

方式三:

在所有使用POST操作的ajax前面,插入以下代碼。

這段代碼會在送出請求前,將csrf的字串放入請求頭中。你也不用在每個ajax請求中,加入 headers:{"X-CSRFToken":$.cookie('csrftoken')} 這段代碼了。

<script src="/static/jquery-3.4.1.js" charset="utf-8"></script>

  var csrftoken = $.cookie('csrftoken');

  function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); //用來判斷是否非POST方法
  }
  $.ajaxSetup({
    beforeSend: function(xhr, settings) {
      if (!csrfSafeMethod(settings.type /*請求方式*/ ) && !this.crossDomain) {
        xhr.setRequestHeader("X-CSRFToken", csrftoken);
      }
    }
  });

在學會處理csrf跨域請求後,我們就可以開始進入檔案上傳的內容了。

最基本的檔案上傳就是使用form提交

<form action="/file_put/" method="POST" enctype="multipart/form-data">
  {% csrf_token %}
    姓名 <input type="text" name="user">
    文件 <input type="file" name="file_obj">
    <input type="submit" />
</form>

因為一般的form提交是以urlcode的格式提交數據,但是上傳檔案需要用不同的格式上傳,因此需要使用 enctype="multipart/form-data" 來告訴瀏覽器這次提交的事檔案類型的數據。

瀏覽器上傳以後,就要由後台接收數據了,瀏覽器會將數據提交到form action 中所定的url中。

後台view就要使用這個url定義一個處理的函數。

from app import settings
def file_put(request):
    print(request.POST,request.FILES)
    file_obj = request.FILES.get('file_obj')
    #文件物件有一個name屬性,獲取文件名稱字符串
    path = os.path.join(settings.BASE_DIR,"media",file_obj.name) #將上傳目的文件夾join到django目錄中
    with open(path,'wb') as f:
        for line in file_obj:
            f.write(line)
        #另一種寫法,使用chunks()方法
        #for item in file_obj.chunks():
        #   f.write(item);
    return HttpResponse('OK')

使用基於jquery ajax的檔案上傳

<form>
    {% csrf_token %}
    姓名 <input type="text" id="user">
    文件 <input type="file" name="file_obj" id="file">
    <input type="button" class="filebtn" value="upload file"/>
</form>
$('.filebtn').click(function(){     //在javascript中榜定一個事件
      //使用FormData處理formdata格式
      var formdata = new FormData();
      var file = document.getElementByID("file").files[0];
      //在formdata加入數據
      formdata.append("file_obj",file);
      formdata.append("user",$('#user').val());
      $.ajax({
        url:"/bookstore/file_put/",
        type:"POST",
        data:formdata,
        processData: false,    //告訴瀏覽器不要特別處理數據
        contentType: false,
        success:function(data){
          console.log(data);
        },
      });
    });

使用原生ajax的檔案上傳:

function xhrSubmit() {
      // $("#file")[0]
      var file_obj = document.getElementById("file").files[0];
      var fd = new FormData();
      fd.append('username', 'root');
      fd.append(file_obj', file_obj);

      var xhr = new XMLHttpRequest();
      xhr.open("POST", '/file_put/', true);
      xhr.send(fd);
      xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
          var obj = JSON.parse(xhr.responseText);
          console.log(obj);
        };
      };
    }

基於iframe的檔案上傳:

<form action="/app01/upload_file/" method="POST" enctype="multipart/form-data" target="ifml">
    {% csrf_token %}
    <iframe id="ifml" name="ifml"></iframe>
    <input type="file" name="fafafa"/>
    <input type="submit" name="iframeSubmit" onclick="iframeSubmit();"/>
</form>
<div id="preview"><!--圖片預覽-->

</div>
function iframeSubmit() {
      $('#ifml').load(function(){
        var text = $('#ifml').contents().find('body').text();
        var obj = JSON.parse(text);
        $('#preview').empty();
        var imgTag = document.createElement('img');
        imgTag.src = "/" + obj.data;
        print(obj.data);
        $('#preview').append(imgTag);
      });
    }

    function onChangeSubmit(){
      $('#ifml').load(function(){
        var text = $('#ifml').contents().find('body').text();
        var obj = JSON.parse(text);
        $('#preview').empty();
        var imgTag = document.createElement('img');
        imgTag.src = "/" + obj.data;
        print(obj.data);
        $('#preview').append(imgTag);
      });

      $('#ifml').submit();

    }
12-28 21:09