Django下载文件--打开文件后需要主动关闭文件吗

问题来源:

今天在写文件下载接口的时候,使用django的FileResponse对象对文件进行数据的转换

使用FileResponse对象的时候需要先打开文件对象

然后在return response之前,使用f.close()关闭了文件

经过调试发现,文件已经被关闭,不能正常return response

代码报错如下:ValueError: read of closed file

ValueError: read of closed file

由此,导致返回数据失败。前端拿不到正常的文件内容。

其实Djnago提供了三种方式实现文件下载功能,分别是:HttpResponse、StreamingHttpResponse和FileResponse,三者的说明如下:

  1. HttpResponse 是所有响应过程的核心类,它的底层功能类是HttpResponseBase。

  1. StreamingHttpResponse 是在HttpResponseBase 的基础上进行继承与重写的,它实现流式响应输出(流式响应输出是使用Python的迭代器将数据进行分段处理并传输的),适用于大规模数据响应和文件传输响应。

  1. FileResponse 是在StreamingHttpResponse 的基础上进行继承与重写的,它实现文件的流式响应输出,只适用于文件传输响应。

HttpResponse、StreamingHttpResponse和FileResponse 这三者的差异:
  1. HttpResponse 实现文件下载存在很大弊端,其工作原理是将文件读取并载入内存,然后输出到浏览器上实现下载功能。如果文件较大,该方法就会占用很多内存。对于下载大文件,Django推荐使用StreamingHttpResponse 和FileResponse 方法,这两个方法将下载文件分批写入服务器的本地磁盘,减少对内存的消耗。

  1. StreamingHttpResponse 和FileResponse 的实现原理是相同的,两者都是将下载文件分批写入本地磁盘,实现文件的流式响应输出。

  1. 从适用范围来说,StreamingHttpResponse 的适用范围更为广泛,可支持大规模数据或文件输出,而FileResponse 只支持文件输出。

  1. 从使用方式来说,由于StreamingHttpResponse 支持数据或文件输出,因此在使用时需要设置响应输出类型和方式,而FileResponse只需设置3个参数即可实现文件下载功能。

但是对于上述三种方法, 都需要对文件进行读取操作,所以都可能会遇到这个问题,那么该如何解决呢?

为了让文件正常返回,不对文件进行主动关闭,发现可以下载成功。

因此,引发一个问题的思考,如果文件比较大,会不会因为被打开了,又没有主动关闭,从而占用内存,长时间运行导致内存溢出呢?
接下来将对该问题做出测试,并记录测试过程,得出结论。

问题测试过程:

下面将对这个问题做出实际测试:

先使用lsof命令查看文件的打开使用情况:

此时,文件并没有被打开

然后在下载函数中,加一个强制休眠

time.sleep(300)

然后重启django后,重新调用下载文件接口

后端处理卡住的时候,重新查看文件的占用情况

确定文件被占用,截图如下

等待休眠时间完成

重新查看文件的占用情况

发现文件已经没有被占用了

完整过程截图:

所以,得到结论是

Django下载文件--打开文件后需要主动关闭文件吗?---->【不需要】

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JamesDanni

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值