2010-03-17 4 views
7

Tôi đang cố tải xuống tệp CSV bằng cách sử dụng HttpResponse để đảm bảo rằng trình duyệt coi đó là tệp đính kèm. Tôi làm theo hướng dẫn được cung cấp here nhưng trình duyệt của tôi không nhắc nhở hộp thoại "Lưu dưới dạng". Tôi không thể tìm ra điều gì sai với chức năng của mình. Tất cả trợ giúp đều được đánh giá cao.Tải xuống tệp csv trong django

 
    dev savefile(request): 
     try: 
      myfile = request.GET['filename'] 
      filepath = settings.MEDIA_ROOT + 'results/' 
      destpath = os.path.join(filepath, myfile) 
      response = HttpResponse(FileWrapper(file(destpath)), mimetype='text/csv') 
      response['Content-Disposition'] = 'attachment; filename="%s"' %(myfile) 
      return response 
     except Exception, err: 
      errmsg = "%s"%(err) 
      return HttpResponse(errmsg) 

ngày Happy Pat!

Trả lời

1

Cảm ơn tất cả mọi người cho ý kiến ​​của bạn. Tuy nhiên, tôi nghĩ rằng tôi đã tìm thấy câu trả lời cho vấn đề của mình ở đây: Downloading CSV via AJAX Chức năng "savefile" của tôi được gọi qua một yêu cầu Ajax và có vẻ như ajax có giới hạn trong đó "lưu dưới dạng hộp thoại "không xuất hiện bất kể tiêu đề HTTP là gì.

Tôi nên đề cập rằng tôi sử dụng Ajax để gọi chức năng này nhưng nó không bao giờ xảy ra với tôi rằng điều này có thể là một vấn đề. :) Thankyou StackOverflow!

5

Bạn đã thử xác định loại nội dung chưa? ví dụ:

response['Content-Type'] = 'application/x-download'; 

Edit:

Lưu ý, mã này gây nên thành công một "Save As" hộp thoại cho tôi. Lưu ý tôi chỉ định "application/x-download" trực tiếp trong đối số mimetype. Bạn cũng có thể muốn kiểm tra lại mã của bạn và đảm bảo đường dẫn tệp của bạn là chính xác và FileWrapper() không làm điều gì đó kỳ lạ.

def save_file(request): 
    data = open(os.path.join(settings.PROJECT_PATH,'data/table.csv'),'r').read() 
    resp = django.http.HttpResponse(data, mimetype='application/x-download') 
    resp['Content-Disposition'] = 'attachment;filename=table.csv' 
    return resp 
+0

đã dùng thử, vẫn không hoạt động. Tôi có thể thấy phản hồi và tiêu đề trong FireBug nhưng tôi không nhận được hộp thoại. – spyder

+0

Thử chỉnh sửa hiện tại của tôi. – Cerin

+0

Tôi đã thử nhưng không hoạt động. Xin vui lòng xem trả lời của tôi, tôi phát hiện ra vấn đề không có gì để làm với django. Cảm ơn – spyder

7

Nếu tập tin là tĩnh (nghĩa là không được tạo ra đặc biệt cho yêu cầu này), bạn không nên phục vụ nó thông qua django anyway. Bạn nên cấu hình một số đường dẫn (như/static /) để được phục vụ bởi máy chủ web của bạn, và lưu tất cả các chi phí django.

Nếu tập tin là động, có 2 lựa chọn:

  1. Tạo nó trong bộ nhớ và phục vụ nó từ django.
  2. Tạo nó trên đĩa và trả lại một HttpResponseRedirect cho nó, sao cho máy chủ web của bạn giao dịch với bản tải xuống (nếu tệp quá lớn, bạn nên sử dụng tùy chọn này).

Đối với phục vụ nó tự động, tôi đã sử dụng đoạn mã sau (mà là một phiên bản đơn giản của ExcelResponse)

import StringIO 
from django.db.models.query import ValuesQuerySet, QuerySet 

class CSVResponse(HttpResponse): 

    def __init__(self, data, output_name='data', headers=None, encoding='utf8'): 

    # Make sure we've got the right type of data to work with 
    valid_data = False 
    if isinstance(data, ValuesQuerySet): 
     data = list(data) 
    elif isinstance(data, QuerySet): 
     data = list(data.values()) 
    if hasattr(data, '__getitem__'): 
     if isinstance(data[0], dict): 
      if headers is None: 
       headers = data[0].keys() 
      data = [[row[col] for col in headers] for row in data] 
      data.insert(0, headers) 
     if hasattr(data[0], '__getitem__'): 
      valid_data = True 
    assert valid_data is True, "CSVResponse requires a sequence of sequences" 

    output = StringIO.StringIO() 
    for row in data: 
     out_row = [] 
     for value in row: 
      if not isinstance(value, basestring): 
       value = unicode(value) 
      value = value.encode(encoding) 
      out_row.append(value.replace('"', '""')) 
     output.write('"%s"\n' % 
        '","'.join(out_row))    
    mimetype = 'text/csv' 
    file_ext = 'csv' 
    output.seek(0) 
    super(CSVResponse, self).__init__(content=output.getvalue(), 
             mimetype=mimetype) 
    self['Content-Disposition'] = 'attachment;filename="%s.%s"' % \ 
     (output_name.replace('"', '\"'), file_ext) 

Để sử dụng nó, chỉ cần sử dụng trở lại CSVResponse (...) đi qua trong danh sách các danh sách, một danh sách các dicts (có cùng các khóa), một QuerySet, một ValuesQuerySet

+0

Nó được tạo ra khi đang bay cho yêu cầu "này" và được lưu tạm thời dưới/static /. – spyder

+0

Đã chỉnh sửa sau khi bình luận của bạn –

+0

Cảm ơn bạn đã biết chi tiết ! – spyder

0

Liệu nó có tạo ra bất kỳ sự khác biệt nào nếu bạn không kèm theo tên tệp trong dấu ngoặc kép không? Mẫu mã không trích dẫn filename:

response['Content-Disposition'] = 'attachment; filename=foo.xls' 

nhưng mã của bạn không:

response['Content-Disposition'] = 'attachment; filename="foo.xls"' 
+0

Cảm ơn, đã thử nó ... không có niềm vui. – spyder

0

Thomas, tôi đã sử dụng một hàm Ajax để lưu và tải xuống tệp này.Dường như trong trường hợp này, hộp "Lưu dưới dạng" sẽ không xuất hiện bất kể tiêu đề. Tôi chỉ đơn giản là sử dụng javascript để tải về tập tin đó. window.open ("đường dẫn/đến/tệp"); và thực hiện thủ thuật. Tôi đã thử nghiệm trên IE6 và Firefox và hộp thoại xuất hiện.