因为某些原因,不想使用imagefield字段,而是将上传的所有图片地址统一返回前端
之前在
如何使用pathlib优雅地抛弃open写入
更新时间:2021-04-29 09:00:04
一文中提出了这样的方法,但是今天前端的朋友给我反馈
当时看见这个,我还不太相信,于是去测试了一番api
哇,生成这么多残缺的图片
测试期间生成的图片实在有些多..
原版
save_path = pathlib.Path(settings.MEDIA_ROOT) / get_type / f'{uuid.uuid4().hex}{pathlib.Path(form)}' if not pathlib.Path(settings.MEDIA_ROOT).is_dir(): pathlib.Path(settings.MEDIA_ROOT).mkdir(parents=True) for content in img.chunks(): save_path.write_bytes(content) ready_save.append((pathlib.Path(settings.MEDIA_URL) / get_type / f'{save_path.name}').as_posix()) save_path = pathlib.Path(settings.MEDIA_ROOT) / get_type / f'{uuid.uuid4().hex}{pathlib.Path(form)}'
看源代码...就发现了问题
save_path 的重新赋值多余了...,可以看看之前的文章,每次的for已经赋值过了,我想为什么会存在,可能是我之前从os改为pathlib时,没有改完全吧。
还有为什么出了这么多的uri,我们看返回的关键字典ready_save,原来这里的ready_save在for里有问题,为什么有问题呢?
这也是我在这里讲的为什么是大容量图片优化版!!!,对于上次的文章代码来说,出了save_path 赋值重复这个小问题,ready_save在哪都没有问题
我们首先得print(content)
看看,再增加个区分符
这样我们就能发现问题,大容量的图片,content分两次出来了,每次都只是部分图片信息,所以保存的图片才是残缺的,而小容量的图片for就只有一次,所以content根本不需要拼接!!!所以我才说在哪都一样。
这里放出优化版的
insert_content = b'' for content in img.chunks(): insert_content += content save_path.write_bytes(insert_content) ready_save.append((pathlib.Path(settings.MEDIA_URL) / get_type / f'{save_path.name}').as_posix())
注意图片信息已经写入的是二进制,所以我们得赋值个二进制编码!!!
然后我们人为的来拼接,再去读取写入
到这里,可能会有人问,chunks()是什么啊
我看到有对这个的阐述
class UploadedFile
在文件上传的期间,实际的文件数据被存储在request.FILES。在这个字典中的每一项都是一个UploadedFile对象或者是子类的对象。这是一个对已经上传文件的简单封装,你可以通过以下方法进行访问上传的内容。
方法:
read()
从该文件中读取整块上传的数据,使用这个方法必须小心,如果该上传的文件特别大,它将使得你的系统崩溃,相反你可以使用chunks()方法来一小块小块的读取到内存中。
multiple_chunks(chunk_size=None)
如果上传的文件足够大需要在多个块(chunks)中进行读取,将会返回True。默认情况下,这将会是任何大于2.5 MB的文件,但是这个是可以配置的。
chunks()
这个一个返回文件chunks的生成器。如果multiple_chunks()为True,你应该在循环中使用这个方法而不是read()。
实际上,经常最简单的使用方法是总是使用chunks()。然后循环这个chunks()方法而不是使用read(),这样确保大文件不会过分占用你的系统内存。
引用 https://www.cnblogs.com/baishoujing/p/7209886.html
看完了这些,你应该就知道chunks()的作用了!