django+jquery 用post方式上传文件采坑记录

文章目录

  • 前言
  • 1. 前端布局
  • 2. django 设置
  • 3. JS 实现对上传操作的控制
    • 3.1 失败版 .ajax
    • 3.2 失败版 .ajaxSubmit
    • 3.3 成功版 直接用submit


前言

最近用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无法正确跳转,即便写成一样的也不行,不写的话他会默认提交到当前页面,肯定也是不行的。后面打算在试一试,总之当下的问题是暂时解决了。

你可能感兴趣的:(javascript,jquery,html,django)