Django로 다운로드 할 파일 생성


96

zip 아카이브를 만들어 다운로드하도록 제공 할 수 있지만 여전히 파일을 하드 드라이브에 저장할 수 없습니까?

답변:


111

다운로드를 시작하려면 Content-Disposition헤더 를 설정해야합니다 .

from django.http import HttpResponse
from wsgiref.util import FileWrapper

# generate the file
response = HttpResponse(FileWrapper(myfile.getvalue()), content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=myfile.zip'
return response

디스크에 파일을 저장하지 않으려면 다음을 사용해야합니다. StringIO

import cStringIO as StringIO

myfile = StringIO.StringIO()
while not_finished:
    # generate chunk
    myfile.write(chunk)

선택적으로 Content-Length헤더도 설정할 수 있습니다.

response['Content-Length'] = myfile.tell()

1
나는 콘텐츠 길이 장고 미들웨어 자동으로 발생할 수있는 생각
andrewrk

4
이 예제를 사용하면 항상 비어있는 파일을 다운로드합니다. 아이디어가 있습니까?
camelCase

3
@ eleaz28이 말했듯이 내 경우에도 빈 파일을 생성했습니다. 방금을 제거했고 FileWrapper작동했습니다.
Sébastien

이 답변은 Django 1.9에서 작동하지 않습니다. 참조 : stackoverflow.com/a/35485073/375966
Afshin Mehrabani

1
읽기 모드에서 파일을 열면 file.getvalue () 속성 오류가 발생합니다. TextIOWrapper 속성 getValue가 없습니다.
Shubham Srivastava

26

임시 파일을 만드는 것이 더 즐거울 것입니다. 이것은 많은 메모리를 절약합니다. 동시에 한 명 또는 두 명 이상의 사용자가있을 때 메모리 절약이 매우 중요하다는 것을 알게 될 것입니다.

그러나 StringIO 개체에 쓸 수 있습니다 .

>>> import zipfile
>>> import StringIO
>>> buffer= StringIO.StringIO()
>>> z= zipfile.ZipFile( buffer, "w" )
>>> z.write( "idletest" )
>>> z.close()
>>> len(buffer.getvalue())
778

"버퍼"개체는 778 바이트 ZIP 아카이브가있는 파일과 유사합니다.


2
메모리 절약에 대한 좋은 점. 그러나 임시 파일을 사용하는 경우 삭제할 코드를 어디에 넣을까요?
andrewrk

@ superjoe30 : 정기 정리 작업. Django에는 이전 세션을 제거하기 위해 주기적으로 실행해야하는 admin 명령이 이미 있습니다.
S.Lott 2010-06-18

@ superjoe30 그 / tmp를 :)을 위해 무엇의
aehlke

@ S.Lott mod x-sendfile을 사용하여 생성 된 파일 (예 : z in)을 제공 할 수 있습니까?
Miind

10

대신 tar 파일을 만드는 것은 어떨까요? 이렇게 :

def downloadLogs(req, dir):
    response = HttpResponse(content_type='application/x-gzip')
    response['Content-Disposition'] = 'attachment; filename=download.tar.gz'
    tarred = tarfile.open(fileobj=response, mode='w:gz')
    tarred.add(dir)
    tarred.close()

    return response

1
장고의 최신 버전이 들어 있어야한다 content_type=대신mimetype=
기욤 Lebreton


6

models.py

from django.db import models

class PageHeader(models.Model):
    image = models.ImageField(upload_to='uploads')

views.py

from django.http import HttpResponse
from StringIO import StringIO
from models import *
import os, mimetypes, urllib

def random_header_image(request):
    header = PageHeader.objects.order_by('?')[0]
    image = StringIO(file(header.image.path, "rb").read())
    mimetype = mimetypes.guess_type(os.path.basename(header.image.name))[0]

    return HttpResponse(image.read(), mimetype=mimetype)

이미지 크기의 메모리 내 문자열을 만드는 것이 안전하지 않은 것 같습니다.
dhill


5
def download_zip(request,file_name):
    filePath = '<path>/'+file_name
    fsock = open(file_name_with_path,"rb")
    response = HttpResponse(fsock, content_type='application/zip')
    response['Content-Disposition'] = 'attachment; filename=myfile.zip'
    return response

요구 사항에 따라 zip 및 콘텐츠 유형을 바꿀 수 있습니다.


1
의미fsock = open(filePath,"rb")
stelios aug

4

메모리 내 tgz 아카이브와 동일 :

import tarfile
from io import BytesIO


def serve_file(request):
    out = BytesIO()
    tar = tarfile.open(mode = "w:gz", fileobj = out)
    data = 'lala'.encode('utf-8')
    file = BytesIO(data)
    info = tarfile.TarInfo(name="1.txt")
    info.size = len(data)
    tar.addfile(tarinfo=info, fileobj=file)
    tar.close()

    response = HttpResponse(out.getvalue(), content_type='application/tgz')
    response['Content-Disposition'] = 'attachment; filename=myfile.tgz'
    return response
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.