ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Django 文件上传和下载功能

2021-01-04 16:58:30  阅读:230  来源: 互联网

标签:文件 Django content myFile 上传 下载


文件下载功能

相应内容除了返回网页的信息外,还可以实现文件的下载功能,Django提供三种下载文件的功能,分别是:HttpResponse,StreamingHttpResponse,FileResponse.

  • HttpResponse:是所有响应过程的核心类,它的底层功能类是HttpResponseBase
  • StreamingHttpResponse:是在HttpResponseBase的基础上进行继承和重写的,它实现流式响应输出(是使用python的迭代器将数据进行分段处理并输出)。适用于大型规模数据响应和文件传输响应
  • FileResponse:是在StreamingHttpResponse的基础上继承重写的,它实现文件的流式响应输出,只适合用于文件传输和响应
class StreamingHttpResponse(HttpResponseBase):
    
    streaming = True

    def __init__(self, streaming_content=(), *args, **kwargs):
        super().__init__(*args, **kwargs)
        # `streaming_content` should be an iterable of bytestrings.
        # See the `streaming_content` property methods.
        self.streaming_content = streaming_content
  • streaming_content:的数据格式可设为迭代器对象或字节流,代表数据或文件内容
  • *args, **kwargs:设置HttpResponseBase的参数,即响应内容的数据格式,content_type和响应状态码status等参数。

若使用StreamingHttpResponswene实现文件下载,则文件以字节的方式读取,在StreamingHttpResponse实列化时传入文件的字节流,由于该类支持数据或文件内容的响应方式输出,因此还需设置响应内容的数据格式和文件下载格式。

class FileResponse(StreamingHttpResponse):
    """
    A streaming HTTP response class optimized for files.
    """
    block_size = 4096

    def __init__(self, *args, as_attachment=False, filename='', **kwargs):
        self.as_attachment = as_attachment
        self.filename = filename
        super().__init__(*args, **kwargs)
  • as_attachment:的数据类型为布尔类型,若为False,则不提供文件下载功能,文件将会在浏览器打开并读取,若浏览器无法打开文件,则将文件下载到本地计算机,但没有设置文件的后辍吗,若为True,则开启文件下载功能,将文件下载到本地计算机并设置文件后辍名。
  • filename:设置下载文件的文件名,该参数和参数as_attachment的设置参数有关,若参数as_attachment为False,则参数filename不做任何作用,在as_attachment为True的情况下,若参数filename为空的情况下,则使用该文件原有的文件名作为下载文件的文件名,反之以filename的参数为文件名
  • *args, **kwargs:用于设置HttpResponseBase的参数,即响应内容的数据格式,content_type和响应状态码status等参数

​​​​

urlpatterns=[
    path('file1',views.download1,name='download1'),
    path('file2',views.download2,name='download2'),
    path('file3',views.download3,name='download3')

]

def index(request):
    return render(request,'index-1.html')

def download1(request):
    file_path='D:\cot.jpg'
    try:
        r=HttpResponse(open(file_path,'rb'))
        r['content_type']='application/octet-stream'
        r['Content-Disposition']='attachment;filename=cat.jpg'
        return r
    except Exception:
        raise Http404('错误')

def download2(request):
    file_path='D:\coe.jpg'
    try:
        r = StreamingHttpResponse(open(file_path, 'rb'))
        r['content_type'] = 'application/octet-stream'
        r['Content-Disposition'] = 'attachment;filename=coe.jpg'
        return r
    except Exception:
        raise Http404('错误')

def download3(request):
    file_path='D:\coa.jpg'
    try:
        f=open(file_path, 'rb')
        r = FileResponse(f,as_attachment=False,filename='dog.jpg')
        return r
    except Exception:
        raise Http404('错误')
  1. 视图函数download1使用HttpResponse实现文件下载,将文件以字节流的方式读取并传入响应类HttpResponse进行实列化,并对实列化对象r设置参数content_type和Content-Disposition,这样就可以实现下载
  2. 视图函数download2使用StreamingHttpResponse实现下载,使用方式和HttpResponse相同
  3. 视图函数download3使用FileResponse实现文件下载,该类的使用方式最为简单,将文件以字节流的方式读取并设置参数as_attachment和filename,然后将三者一并传入FileResponse进行实列化即可

​​​​​​​三者之间的差异

  • HttpResponse:实现文件下载会有很大的弊端,其工作原理的是文件读取并载入内存,然后输出到浏览器上实现下载功能,如果下载的文件过大,该方法就会占用很大的内存,对于文件下载,Django推荐使用StreamingHttpResponse,FileResponse,这两个方法将下载文件分批写入服务器的本地磁盘,而不在将文件载入服务器的内存。
  • 从适合范围来说,StreamingHttpResponse的适用方式更为广泛,可支持大规模数据或文件输出,而FileResponse只支持文件输出
  • 从使用方式来说,由于StreamingHttpResponse支持数据和文件输出,因此在使用时候需要设置响应输出类型和方式,而FileResponse只需要设置3个参数即可实现文件下载功能

 

文件上传功能

 

import os
def index(request):
    if request.method=='POST':   #判断是否为POST请求
        myFile=request.FILES.get('myfile',None)
        print(myFile)
        if not myFile:
            return HttpResponse('no file for index')
        f=open(os.path.join('D:\sword',myFile.name),'wb+')
        print(f)
        for chunk in myFile.chunks():  #分块写入文件
            print(chunk)
            f.write(chunk)
        f.close()
        return HttpResponse('index over')
    else:
        return render(request,'index.html')#请求方法为GET时候,生成文件上传页面
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="myfile" >
    <input type='submit' value="文件上传">

</form>
  1. 模板文件index.html使用form标签的文件控件file生成文件的上传功能,该控件将用户上传的文件以二进制读取,读取方式由form标签的属性enctype="multipart/form-data"设置
  2. 浏览器将用户上传的文件读取后,通过HTTP的post请求将二进制的文件 传到Django当Django收到post请求后,从请求对象属性FILES获取文件信息,然后在D盘的sword文件里创建文件,文件名从myFile.name获取,与用户上传的文件名字相同。
  3. 从文件信息对象myFile.chunks()读取文件内容,并写入D盘中,从而实现文件的上传功能。

​​​​​​​如果将form标签属性enctype="multipart/form-data"去掉,当用户在浏览器操作文件上传的时候,Django无法从请求对象里面FILES获取文件信息,file变为请求参数的形式传递

上述的myFile包含文件的基本信息,比如文件名,大小和后辍名。

  • myFile.name:获取上传文件的文件名,包含文件的后辍名
  • myFile.size:获取文件上传的大小
  • myFile.content_type:获取文件的类型,通过后续名判断文件的类型

​​​​​​​从文件对象myFile获取文件内容,Django提供以下属性来获取文件信息

  • myFile.read():从文件对象里读取整个文件的长传的数据,这个方法只适合小文件
  • myFile.chunks:按流式响应方式读取文件,,在for循环中进行迭代,将文件分块写入服务器所的指定位置
  • myFile.multipe_chunks:判断文件对象的文件大小,返回布尔值,当文件大于2.5MB,返回True,否则返回Flase.

源文件

class UploadedFile(File):
#文件上传的基本功能类,继承父类file,该类主要获取文件的文件名,大小和类型等基本信息
class TemporaryUploadedFile(UploadedFile):
#将文件数据临时存放在服务器所指定的文件里,适用于大文件的上传
class InMemoryUploadedFile(UploadedFile):
#将文件数据存在内存里,适用于小文件的上传
class SimpleUploadedFile(InMemoryUploadedFile):
#将文件名,大小和类型生成字典


myFile.chunks,myFile.read读取文件内容时候,其实质分别是调用InMemoryUploadedFile, TemporaryUploadedFile来实现文件上传的,两者之间的区别在于保存上传文件之前,文件数据需要存放在某个位置,默认情况下,当大小小于2.5MB的时候Django会通过InMemoryUploadedFile把上传的文件全部内容读进内存当上传文件大于2.5MB时候,Django会使用TemporaryUploadedFile把上传的文件写到临时文件中,从而节省内存的开销

在这4个功能类的基础上,Django进一步完善了文件的上传功能,主要完善了文件的创建,读写,和关闭等功能,处理过程在uploadhandler.py该文件定义了7个类和一个函数。7个类可以划分为两个类型,分别是异常处理和程序处理,,异常处理是处理文件上传过程中出现的异常情况,如上传中断,网络延迟,程序处理是实现文件上传过程,其中TemporaryFileUploadHandler是调用TemporaryUploadedFile来实现上传。MemoryFileUploadHandler是调用InMemoryUploadedFile,无论哪个类,Django都为文件上传机制配了4个属性

  • FILE_UPLOAD_MAX_MEMORY_SIZE:判断文件的大小,默认2.5MB
  • FILE_UPLOAD_PERMISSIONS:用于配置文件上传的权限
  • FILE_UPLOAD_TEMP_DIR:用于配置文件数据的临时存放文件
  • FILE_UPLOAD_HANDLERS:设置文件上传的处理过程。
 

 

 

标签:文件,Django,content,myFile,上传,下载
来源: https://blog.csdn.net/qq_51329314/article/details/112151761

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有