django+jquery 用post方式上傳檔案採坑記錄
前言
最近用django做一個線上的語音識別demo,需要上傳語音檔案,前端是bootstrap+jquery,後端是django,在我的理解範圍內,要處理POST上來的檔案,肯定要呼叫django的檢視函式,最關鍵的是他檢視函式觸發的條件是url要發生變化,否則連 request 是什麼型別都判斷不了,更別說儲存處理了。我遇到的問題是,用POST方式提交表單後url一直沒有變化,按道理應該是要跳轉到 action 定義的url裡面,但一直沒有跳轉,所以沒法觸發檢視函式。
先直接上結論,jquery的 .ajax({ }) 和 .ajaxSubmit({ }) 都沒有用,最後還是用傳統的
<input type="submit" id="submit_btn" style="visibility:hidden" />
解決問題,一開始是因為佈局問題不想用它,最後還是妥協一下直接把他隱藏掉。
下面分別貼出嘗試過的方案,包括 js,html和django程式碼
1. 前端佈局
按鈕組和表單, action是表單要提交到的url,也是想要跳轉的url,除了url也可以是php檔案
<div class="btn-group-lg" align="center">
<form method="POST" id="uploadForm" action="{% url 'form' %}" enctype="multipart/form-data">
<input type="file" id="audiofile" name="audiofile" value="audiofile" style="visibility:hidden"/>
<input type="submit" id="submit_btn" style="visibility:hidden"/>
</form>
<button type="button" id="upload_btn" class="btn btn-default" style="width:150px; outline:0">
<span>
<img src="../../static/image/upload.png" class="icon-bar" width="30">
</span>
Upload
</button>
</div>
2. django 設定
- 專案url函式 urls.py
urlpatterns = [
url(r"^demo/$", demo.views.demo, name = "demo"),
url(r"^demo/upload/$", demo.form.upload_file, name = "form")
]
- 主頁面檢視函式 views.py
from django.shortcuts import render
def demo(request):
return render(request, "demo/index.html")
- 表單處理函式(自定義)form.py
import os
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django import forms
from ASR_demo import settings
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
def handle_uploaded_file(f):
file_path = os.path.join(settings.MEDIA_ROOT, "uploadAudio")
with open(file_path, 'wb') as destination:
for chunk in f.chunks():
destination.write(chunk)
def upload_file(request):
if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
# if form.is_valid():
handle_uploaded_file(request.FILES['audiofile'])
return HttpResponseRedirect("/demo/")
else:
return HttpResponse(request.method)
return HttpResponse("OK")
很明顯,upload_file函式用來判斷request型別並且處理上傳的檔案,主頁面url是 localhost:8080/demo/, 觸發該函式的契機是url變成 localhost:8080/demo/upload/, 所以需要上傳後url立刻跳轉,注意這裡的跳轉一定不能是重定向,否則request會直接變成 GET 而不是 POST。
3. JS 實現對上傳操作的控制
3.1 失敗版 .ajax
$("#audiofile").change(function(){
var formData = new FormData();
file = $("#audiofile")[0].files[0];
formData.append("file", file);
formData.append("name", "audiofile");
$.ajax({
url: $("#uploadForm").attr("action"),
type:"POST",
data:formData,
processData:false,
contentType:false,
success: function(){
alert($("#audiofile").attr("value"));
// window.location.replace("/demo/upload/");
},
error: function () {
alert("Failed");
}
});
});
用這種方法可以正確地將檔案上傳到指定url,並且看後臺日誌的時候也可以發現確實是post到了指定的url,
但瀏覽器上的url沒發生變化, django的upload_file函式根本沒法觸發,很尷尬。另外可以看到上面程式碼中用window.location強行重定向到了目標url,但request就會變成GET,同樣拿不到POST檔案。注意區分一下,這個不是所謂的跨域重定向時,POST 變成 GET,那是另外一個問題,讓django支援https的話就可以解決。而我們這裡確實是通過重定向的方式向伺服器請求了這個url,他自然就會變成GET。
3.2 失敗版 .ajaxSubmit
$("#audiofile").change(function(){
$("#uploadForm").ajaxSubmit({
success: function(){
//alert($("#audiofile").attr("value"));
},
error: function(){
alert("Failed");
}
});
});
和前面一樣,同樣可以上傳到指定url,但實際url並沒有跳轉,也就無法觸發對應的檢視函式。
3.3 成功版 直接用submit
這裡就沒什麼程式碼了,很簡單直接 click() 就行:
$("#audiofile").change(function() {
$("#submit_btn").click();
});
這樣做他後面可以直接跳轉到指定url,進而就實現了對POST請求的處理。
後來自己考慮了一下,.ajax 和 **.ajaxSubmit ** 裡面都有一個 url引數,同樣是設定要把檔案或資料上傳到哪裡,這個 url 會不會和表單中的 action 發生了衝突導致url無法正確跳轉,即便寫成一樣的也不行,不寫的話他會預設提交到當前頁面,肯定也是不行的。後面打算在試一試,總之當下的問題是暫時解決了。
相關文章
- 檔案上傳踩坑記及檔案清理原理探究
- post 表單大檔案上傳
- 上傳大檔案-斷點續傳的一中方式的記錄斷點
- Nodejs教程16:POST檔案上傳NodeJS
- 請問上傳的檔案如何傳送post
- ctfshow檔案上傳漏洞做題記錄
- Python模擬HTTP Post上傳檔案PythonHTTP
- 檔案上傳的幾種方式
- Laravel 大檔案分塊上傳錯誤記錄Laravel
- GORM之ErrRecordNotFound採坑記錄GoORM
- mpvue框架搭建採坑記錄Vue框架
- 上傳檔案並目錄打散
- AS上傳Library到JCenter 教程+踩坑記錄
- 阿里雲 oss 檔案上傳 小坑阿里
- SpringMVC中採用簡潔的配置實現檔案上傳SpringMVC
- POST上傳
- laravel-admin 1.x 版本 呼叫前端元件中多圖上傳採坑記錄Laravel前端元件
- 檔案上傳用XML (轉)XML
- Django檔案上傳 -- 適用於單一小檔案上傳Django
- php檔案上傳之多檔案上傳PHP
- 利用PUT方式上傳檔案的方法研究
- Git上傳採坑之ssh-keygenGit
- JSP筆記-檔案上傳JS筆記
- Laravel-admin 的採坑記錄Laravel
- Gradle實戰及Maven專案遷移採坑記錄GradleMaven
- 用Azure CLI批量上傳檔案
- 記錄檔案預覽另一種方式
- c#採用toml做配置檔案的坑過C#TOML
- 單個檔案上傳和批量檔案上傳
- 檔案上傳
- Android 傳送HTTP GET POST 請求以及通過 MultipartEntityBuilder 上傳檔案(二)AndroidHTTPUI
- Communications--1--資料傳輸除錯記錄-bug採坑雷區除錯
- 用“稽核物件”功能記錄檔案刪除記錄物件
- SpringMVC 單檔案上傳與多檔案上傳SpringMVC
- 用ASP.NET上傳大檔案ASP.NET
- 【Hadoop踩坑】HDFS上傳、刪除檔案失敗Hadoop
- 幾種windows到linux上傳檔案的方式WindowsLinux
- Java大檔案上傳、分片上傳、多檔案上傳、斷點續傳、上傳檔案minio、分片上傳minio等解決方案Java斷點