> 웹 프론트엔드 > JS 튜토리얼 > Django에서 파일 다운로드 기능을 구현하는 방법

Django에서 파일 다운로드 기능을 구현하는 방법

php中世界最好的语言
풀어 주다: 2018-04-11 17:17:14
원래의
3317명이 탐색했습니다.

이번에는 Django에서 파일 다운로드 기능을 구현하는 방법을 보여드리겠습니다. Django에서 파일 다운로드 기능을 구현하기 위한 주의사항은 무엇인가요?

Django를 기반으로 구축된 웹사이트가 파일 다운로드 기능을 제공하는 경우 가장 쉬운 방법은 정적 파일을 Nginx에 넘겨 처리하는 것입니다. 그러나 때로는 웹사이트 자체의 로직으로 인해 다음을 통해 다운로드 기능을 제공해야 할 수도 있습니다. Django에서는 페이지 데이터 내보내기 기능(동적으로 생성된 파일 다운로드), 파일을 다운로드하기 전에 사용자 권한을 확인하는 등의 기능을 제공합니다. 따라서 Django에서 파일 다운로드 기능 구현에 대한 연구가 필요하다.

가장 간단한 파일 다운로드 기능 구현

def file_download(request):
  # do something...
  with open('file_name.txt') as f:
    c = f.read()
  return HttpResponse(c)
로그인 후 복사

와 같이 파일 스트림을 HttpResponse 개체에 넣기만 하면 됩니다. 이 방법은 간단하고 투박해서 작은 파일을 다운로드하는 데 적합하지만, 파일이 매우 큰 경우 이 방법은 많은 메모리를 차지하며 심지어 서버 충돌을 일으킬 수도 있습니다

더욱 합리적인 파일 다운로드 기능

Django의 HttpResponse 객체를 사용하면 반복자를 매개변수로 전달할 수 있습니다. 위 코드에서 들어오는 매개변수 c를 반복자로 바꾸면 위의 다운로드 기능이 큰 파일과 작은 파일 모두에 적합하도록 최적화될 수 있으며 Django는 한 단계 더 나아갑니다. StreamingHttpResponse 개체를 사용하는 것이 좋습니다. StreamingHttpResponse 개체는 파일 스트림을 브라우저에 보내는 데 사용됩니다. 파일 다운로드 기능의 경우 StreamingHttpResponse 개체를 사용하는 것이 더 합리적입니다.

따라서 보다 합리적인 파일 다운로드 기능은 먼저 파일 처리를 위한 반복자를 작성한 다음 이 반복자를 StreaminghttpResponse 객체에 매개변수로 전달해야 합니다(예:

from django.http import StreamingHttpResponse
def big_file_download(request):
  # do something...
 
  def file_iterator(file_name, chunk_size=512):
    with open(file_name) as f:
      while True:
        c = f.read(chunk_size)
        if c:
          yield c
        else:
          break
 
  the_file_name = "file_name.txt"
  response = StreamingHttpResponse(file_iterator(the_file_name))
 
  return response
로그인 후 복사

). 파일 다운로드 기능이 다시 최적화되었습니다

위 코드는 파일 스트리밍을 통해 서버의 파일을 브라우저로 전송하는 작업을 완료했습니다. 그러나 파일 스트림은 일반적으로 하드 디스크에 다운로드되지 않고 브라우저에 왜곡된 형태로 표시되므로 일부 최적화가 필요합니다. 파일 스트림을 하드 디스크에 기록하도록 합니다. 최적화는 매우 간단합니다. StreamingHttpResponse 개체의 Content-Type 및 Content-Disposition 필드에 다음 값을 할당하기만 하면 됩니다. 예:

response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="test.pdf"'
로그인 후 복사

전체 코드는 다음과 같습니다:

from django.http import StreamingHttpResponse
def big_file_download(request):
  # do something... 
  def file_iterator(file_name, chunk_size=512):
    with open(file_name) as f:
      while True:
        c = f.read(chunk_size)
        if c:
          yield c
        else:
          break
 
  the_file_name = "big_file.pdf"
  response = StreamingHttpResponse(file_iterator(the_file_name))
  response['Content-Type'] = 'application/octet-stream'
  response['Content-Disposition'] = 'attachment;filename="{0}"'.format(the_file_name) 
  return response
로그인 후 복사

특정 내보내기 파일 형식

Excel 테이블 내보내기

1. 먼저 엑셀 표를 직접 내보내기

먼저 내보낼 데이터를 가져와 목록 형식으로 저장합니다.

그런 다음 데이터는 Excel에 기록되고 스트리밍 방식으로 다운로드할 수 있도록 페이지로 반환됩니다.

rreee

2.json 파일 내보내기

json 파일을 내보내는 것은 Excel만큼 번거롭지 않습니다. json 형식 데이터를 연결하기만 하면 됩니다. 로컬로 직접 내보내는 것은 여전히 ​​매우 간단합니다. 그러나 웹 페이지로 내보낼 때 스트림을 저장하지 않고 어떻게 직접 반환할 수 있습니까? Excel을 내보내는 것과 같은 로컬?

rreee

3. 압축 패키지 내보내기

두 파일을 내보내면 두 파일을 동시에 반환할 수 없으므로 두 파일을 패키지에 넣은 다음 패키지를 스트림으로 반환하는 것이 좋습니다.

생각하다? 이때 내보내는 것은 zip 패키지입니다. 이 두 파일 스트림을 zip 패키지에 어떻게 작성합니까? 이후 사장님의 안내에 따라 패키징할 파일을 로컬에 저장하고 zip으로 패키징한 후 로컬 파일을 삭제한 후 zip 파일 스트림을 읽어 응답에 쓰고 zip으로 돌려보냈다. 파일 스트림.

import xlwt
import io
import json
from django.http import HttpResponse
def set_style(name, height, bold=False):
  style = xlwt.XFStyle() # 初始化样式
  font = xlwt.Font() # 为样式创建字体
  font.name = name # 'Times New Roman'
  font.bold = bold
  font.color_index = 000
  font.height = height
  style.font = font
  # 设置单元格边框
  # borders= xlwt.Borders()
  # borders.left= 6
  # borders.right= 6
  # borders.top= 6
  # borders.bottom= 6
  # style.borders = borders
  # 设置单元格背景颜色
  # pattern = xlwt.Pattern()
  # 设置其模式为实型
  # pattern.pattern = pattern.SOLID_PATTERN
  # 设置单元格背景颜色
  # pattern.pattern_fore_colour = 0x00
  # style.pattern = pattern
  return style
def write_excel(data, name, header):
  # 打开一个Excel工作簿
  file = xlwt.Workbook()
  # 新建一个sheet,如果对一个单元格重复操作,会引发异常,所以加上参数cell_overwrite_ok=True
  table = file.add_sheet(name, cell_overwrite_ok=True)
  if data is None:
    return file
  # 写标题栏
  row0 = [u'业务', u'状态', u'北京', u'上海', u'广州', u'深圳', u'状态小计']
  for i in range(0, len(row0)):
    table.write_merge(0, 0, i, i, row0[i], set_style('Times New Roman', 220, True))
  table.write_merge(0, 2, 7, 9, "单元格合并", set_style('Times New Roman', 220, True))
  """
  table.write_merge(x, x + m, y, w + n, string, sytle)
x表示行,y表示列,m表示跨行个数,n表示跨列个数,string表示要写入的单元格内容,style表示单元格样式。其中,x,y,w,h,都是以0开始计算的。
  """
  l = 0
  n = len(header)
  # 写入数据
  for line in data:
    for i in range(n):
      table.write(l, i, line[header[i]])
    l += 1
  # 直接保存文件
  # file.save("D:/excel_name.xls")
  # 写入IO
  res = get_excel_stream(file)
  # 设置HttpResponse的类型
  response = HttpResponse(content_type='application/vnd.ms-excel')
  from urllib import parse
  response['Content-Disposition'] = 'attachment;filename=' + parse.quote("excel_name") + '.xls'
  # 将文件流写入到response返回
  response.write(res)
  return response
def get_excel_stream(file):
  # StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。
  excel_stream = io.BytesIO()
  # 这点很重要,传给save函数的不是保存文件名,而是一个BytesIO流(在内存中读写)
  file.save(excel_stream)
  # getvalue方法用于获得写入后的byte将结果返回给re
  res = excel_stream.getvalue()
  excel_stream.close()
  return res
로그인 후 복사

이 기사의 사례를 읽으신 후 방법을 마스터하셨다고 생각합니다. 더 흥미로운 정보를 보려면 PHP 중국어 웹사이트의 다른 관련 기사를 주목하세요!

추천 자료:

vue가 xe-utils 함수 라이브러리를 사용하는 단계에 대한 자세한 설명

vue2.0 라우팅에 라우터 뷰가 표시되지 않는 문제를 처리하는 방법

네이티브 방법 가져오기를 사용하여 이미지 업로드 기능을 구현합니다

위 내용은 Django에서 파일 다운로드 기능을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿