文件上傳:
· 一般文件上傳都是采用post請求方式,get請求攜帶的數據有限,有post請求的數據放在請求體中,大小不受約束,但是在django的post請求中要注意csrf(防跨站偽造請求)認證機制;
· 文件上傳使用的是multipart/form-data數據格式傳輸,在使用from表單時需要指定屬性enctype="multipart/form-data";在使用ajax時要設置參數:processData: false,contentType: false,文件對象數據的獲取需要通過js操作標簽DOM對象的files屬性取值獲取($('#file')[0].files[0]單個文件),同時data數據使用FormData對象。在后端django將文件對象(類似文件句柄)保存在請求對象的request.FILES字典中。
· 在實際應用中,可以通過js代碼操作DOM對象的files文件數組,獲取到當前上傳文件對象,判斷文件格式和大小
form表單上傳文件:
upload.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> 6 <title>upload</title> 7 </head> 8 <body> 9 <!--form上傳文件:form標簽必須加上enctype屬性,指定內容傳輸格式--> 10 <div> 11 <form action="{% url 'upload' %}" method="post" enctype="multipart/form-data"> 12 {% csrf_token %} 13 用戶名:<input type="text" name="username"><br> 14 密碼:<input type="password" name="password"><br> 15 上傳文件:<input type="file" name="file"> 16 <br><input type="submit"> 17 </form> 18 </div> 19 </body> 20 </html>
urls.py
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls), 3 url(r'^upload/', views.upload,name='upload'), 4 ]
views.py
1 # form 表單上傳文件: 2 # form頁面需要指定屬性enctype='multipart/form-data' 3 #后端獲取文件用request.FILES 4 5 def upload(request): 6 if request.method=='GET': 7 return render(request,'upload.html') 8 elif request.method=='POST': 9 name=request.POST.get('username') 10 psd=request.POST.get('password') 11 12 # 文件獲取用FILES,獲取的file_obj類似文件句柄 13 file_obj=request.FILES.get('file')#文件對象 14 file_name = file_obj.name #文件名 15 16 # print('>>>>',file_obj,type(file_obj)) 17 # print(file_name) 18 19 #下載寫入文件 20 file_path=os.path.join(settings.BASE_DIR,'upload_files',file_name) 21 with open(file_path,'wb')as f: 22 # (1)文件過大不宜使用 23 ''' 24 f.write(file_obj.read()) 25 ''' 26 # (2)每次讀取以\r\n為界,數據長度不固定,沒有\r\n數據會很大,不宜使用 27 ''' 28 for data in file_obj: 29 f.write(data) 30 ''' 31 #(3)chunks()默認一次返回大小為經測試為65536B,也就是64KB,最大為2.5M,是一個生成器 32 for chunk in file_obj.chunks(): 33 f.write(chunk) 34 35 return HttpResponse('form上傳文件') 36
AJAX上傳文件:
upload.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> 6 <title>upload</title> 7 </head> 8 <body> 9 <!--ajax上傳文件--> 10 <div> 11 {% csrf_token %} 12 用戶名:<input type="text" id="username"><br> 13 密碼:<input type="password" id="password"><br> 14 上傳文件:<input type="file" id="file"><br> 15 <input type="button" id="submit" value="ajax上傳文件"> 16 </div> 17 </body> 18 <script> 19 $(function () { 20 $('#submit').click(function () { 21 //ajax上傳文件必須通過FormData對象傳輸數據 22 var formdata = new FormData(); 23 24 var username = $('#username').val(); 25 var psd = $('#password').val(); 26 var csrf_data = $('input[name=csrfmiddlewaretoken]').val(); 27 //獲取上傳文件對象(文件句柄):定位對象,轉成DOM對象,取值(文件對象列表) 28 var file = $('#file')[0].files[0]; 29 30 formdata.append('username', username); 31 formdata.append('psd', psd); 32 formdata.append('csrfmiddlewaretoken', csrf_data);//csrf認證的鍵是固定的 33 formdata.append('file', file); 34 35 $.ajax({ 36 url: "{% url 'upload' %}", 37 type: 'post', 38 data: formdata, 39 processData: false,//不處理數據 40 contentType: false,//不設置內容類型,按原格式傳輸 41 success: function (response) { 42 alert(response) 43 } 44 }) 45 }) 46 }) 47 </script> 48 </html>
urls.py
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls), 3 url(r'^upload/', views.upload,name='upload'), 4 ]
views.py
1 # ajax上傳文件 2 def upload(request): 3 if request.method=='GET': 4 return render(request,'upload.html') 5 elif request.method=='POST': 6 name = request.POST.get('username') 7 psd = request.POST.get('password') 8 file_obj = request.FILES.get('file') 9 file_name = file_obj.name 10 print('>>>>',file_name) 11 # 拼接絕對路徑 12 file_path = os.path.join(settings.BASE_DIR, 'upload_files', file_name) 13 with open(file_path, 'wb')as f: 14 for chunk in file_obj.chunks():#chunks()每次讀取數據默認我64k 15 f.write(chunk) 16 return HttpResponse('ajax上傳文件')