如何在FastAPI中全程在内存中处理文件上传、MarkItDown转换及Redis存储以减少IO操作?
如何在FastAPI中全程在内存中处理文件上传、MarkItDown转换及Redis存储以减少IO操作?
当然可以全程在内存里完成所有操作,完全不用碰磁盘!你之前的代码里的临时文件IO完全是多余的,咱们直接把所有步骤都放在内存里搞定,效率会高很多。
核心思路就是:不把上传的文件内容写入磁盘,而是用内存中的文件对象(或者直接用字符串/字节)和MarkItDown交互,转换完成后直接把结果存Redis。
下面给你两种可行的方案,你可以根据MarkItDown的实际API支持情况选择:
方案一:直接用字符串/字节处理(最简洁)
如果MarkItDown库支持直接处理字符串或字节内容(比如有convert_string或convert_bytes方法),那这是最直接的方式,连模拟文件都省了:
@router.post("/upload") async def uploadPost(filepond: UploadFile = File()): """ Convert a textual file to markdown. Store in Redis """ # 读取上传文件的字节内容到内存 content_bytes = await filepond.read() # 解码成字符串(假设文件是utf-8编码,若不确定可以用chardet检测) content_str = content_bytes.decode("utf-8") # 直接用字符串转换 md = MarkItDown() result = md.convert_string(content_str) # 直接存入Redis,全程无磁盘IO redis.setex("some key", 3600, result.text_content)
方案二:用内存文件对象模拟磁盘文件
如果MarkItDown的convert方法只接受文件路径或文件-like对象,那咱们用io.BytesIO或者tempfile.SpooledTemporaryFile来模拟内存中的文件,完全不用写磁盘:
import io import tempfile @router.post("/upload") async def uploadPost(filepond: UploadFile = File()): """ Convert a textual file to markdown. Store in Redis """ content_bytes = await filepond.read() # 用BytesIO创建完全在内存中的文件对象 with io.BytesIO(content_bytes) as memory_file: memory_file.seek(0) # 回到文件开头,让MarkItDown可以读取 md = MarkItDown() # 传入内存文件对象进行转换 result = md.convert(memory_file) redis.setex("some key", 3600, result.text_content) # 或者用SpooledTemporaryFile(默认内存处理,超过10MB才会写磁盘,你的4MB文件完全符合) # @router.post("/upload") # async def uploadPost(filepond: UploadFile = File()): # content_bytes = await filepond.read() # with tempfile.SpooledTemporaryFile(suffix=".txt") as spool_file: # spool_file.write(content_bytes) # spool_file.seek(0) # md = MarkItDown() # result = md.convert(spool_file) # redis.setex("some key", 3600, result.text_content)
为什么这两种方案能减少IO?
- 原来的代码需要把上传内容写入临时文件、再让MarkItDown读取该文件、最后还要删除文件,这三次磁盘IO现在都省了。
- 所有操作都在内存中完成,速度更快,也不用处理临时文件的管理问题(比如忘记删除、权限问题等)。
备注:内容来源于stack exchange,提问作者Itay Moav -Malimovka
相关产品推荐
相关产品推荐

