2009-05-12 26 views
15

im gặp khó khăn trong tải nhiều dữ liệu với tên đầu vào tương tự:nhiều file upload sử dụng tên đầu vào tương tự trong django

<input type=file name="file"> 
<input type=file name="file"> 
<input type=file name="file"> 

tại django bên

print request.FILES : 

<MultiValueDict: {u'file': [ 
<TemporaryUploadedFile: captcha_bg.jpg (image/jpeg)>, 
<TemporaryUploadedFile: 001_using_git_with_django.mov (video/quicktime)>, 
<TemporaryUploadedFile: ejabberd-ust.odt (application/vnd.oasis.opendocument.text)> 
]}> 

vì vậy tất cả ba tác phẩm đang được yêu cầu duy nhất. FILES ['tệp'] đối tượng. làm cách nào để xử lý cho từng tệp được tải lên từ đây?

+0

Cùng một vấn đề và giải pháp cho một yếu tố duy nhất với nhiều: ' ' – Mark

Trả lời

49
for f in request.FILES.getlist('file'): 
    # do something with the file f... 

CHỈNH SỬA: Tôi biết đây là câu trả lời cũ, nhưng tôi đã xem nó ngay bây giờ và đã chỉnh sửa câu trả lời để thực sự chính xác. Trước đây, bạn có thể lặp lại trực tiếp qua request.FILES['file']. Để truy cập tất cả các mục trong MultiValueDict, bạn sử dụng .getlist('file'). Chỉ sử dụng ['file'] sẽ chỉ trả lại giá trị dữ liệu cuối cùng mà nó tìm thấy cho khóa đó.

+1

Bất kỳ ý tưởng nào tại sao nó là 'request.FILES ['file']' không hoạt động? Tôi tò mò. – Mark

+0

@Mark nếu bạn có nghĩa là không có tệp nào được tải lên, nó sẽ trả về một chuỗi hoặc danh sách rỗng, nhưng nếu bạn muốn tải lên, nhưng bạn vẫn không thể lấy tệp từ 'request.FILES ['file']' s rất có thể bạn đang thiếu các trường cần thiết trên trường 'input' trong mã html của bạn. Theo kinh nghiệm của tôi, bạn cần sử dụng 'name =" myfile "' trong trường 'input 'để làm cho nó cụ thể. Trong trường hợp này, bạn nên sử dụng 'request.FILES ['myfile']'. Sử dụng 'file' làm tên trong mã html làm cho nó khó phân biệt cái gì là gì. – Ibo

+0

Một điều nữa quan trọng khi giao dịch với nhiều tệp là bao gồm "nhiều/mẫu dữ liệu trong thẻ html' form' của bạn để thẻ biểu mẫu của bạn bao bọc thẻ 'input' của bạn sẽ là'

' – Ibo

1

Tôi không nghĩ rằng tất cả ba tệp sẽ nằm trong đối tượng request.FILES['file'] duy nhất. request.FILES['file'] có khả năng có tệp thứ nhất hoặc tệp cuối cùng từ danh sách đó.

Bạn cần phải đặt tên duy nhất các yếu tố đầu vào như sau:

<input type=file name="file1"> 
<input type=file name="file2"> 
<input type=file name="file3"> 

..for ví dụ.

EDIT: Justin's answer là tốt hơn!

+0

Django tự động xử lý trường hợp có nhiều đầu vào có cùng tên: nó sẽ đưa mã của bạn một danh sách các giá trị thay vì một giá trị duy nhất. Bạn có thể xem danh sách trong mã đã được đăng. –

+0

Vì vậy, 'MultiValueDict' này là kết quả của một trình bao bọc cho đối tượng request.FILES ['file']? –

+0

Có, request.FILES là một đối tượng MultiValueDict, trong khi request.GET và request.POST là các đối tượng QueryDict, tương tự. –

7

Với điểm url của bạn để envia bạn có thể quản lý nhiều file như thế này:

#!/usr/bin/env python 
# -*- coding: UTF-8 -*- 
from django.http import HttpResponseRedirect 

def envia(request): 
    for f in request.FILES.getlist('file'): 
     handle_uploaded_file(f) 
    return HttpResponseRedirect('/bulk/') 

def handle_uploaded_file(f): 
    destination = open('/tmp/upload/%s'%f.name, 'wb+') 
    for chunk in f.chunks(): 
     destination.write(chunk) 
    destination.close() 
+0

Bạn không nên sử dụng tên tệp được cung cấp của người dùng để ghi lên đĩa, nó có thể được thao tác để viết ở bất kỳ đâu. Sử dụng tên tệp ngẫu nhiên và lưu trữ tên tệp gốc trên cơ sở dữ liệu chỉ cho mục đích hiện tại –

Các vấn đề liên quan