使用Office365 REST API上传大文件:如何直传内存数据避免临时文件?
解决Office365 REST API内存直传大文件的问题
你可以通过手动构建上传会话+内存流适配的方式,绕过临时文件直接上传内存中的内容,同时解决多线程下的磁盘IO同步问题。
核心问题分析
你之前尝试直接传入BytesIO失败,是因为create_upload_session默认的参数处理逻辑更偏向真实文件路径/句柄,会尝试调用真实文件特有的方法(比如fileno())。但通过拆分上传流程,先创建会话再处理内存流,就能避开这个限制。
优化方案代码示例
方案1:直接上传内存中的完整文件内容
import io from zipfile import ZipFile from office365.sharepoint.files.file import File # ... 保留原有的下载和解压逻辑 ... for z_file in zip_file.filelist: logger.warning(f"Extracting: {folder.name}_{ab_zip_file.name}_{z_file.filename}, Size: {z_file.file_size}") content = zip_file.read(z_file) upload_fname = z_file.filename if "/" in upload_fname: upload_fname = f'{folder.name}_{upload_fname.partition("/")[2]}' # 用内存流包装文件内容,无需写入临时文件 content_stream = io.BytesIO(content) content_stream.seek(0) # 重置流指针到起始位置 # 创建上传会话(明确指定文件名) upload_session = ab_folder.files.create_upload_session( file_name=upload_fname, chunk_size=3072000 ).execute_query() # 基于内存流执行分块上传 uploader = File(content_stream) upload_session.upload( uploader, chunk_uploaded=print_upload_progress ).execute_query_retry()
方案2:流式读取Zip文件(更省内存)
如果解压后的单个文件达数百MB,推荐直接从Zip中流式读取,避免一次性加载整个文件到内存:
from zipfile import ZipFile from office365.sharepoint.files.file import File # ... 保留原有的下载和解压逻辑 ... for z_file in zip_file.filelist: logger.warning(f"Extracting: {folder.name}_{ab_zip_file.name}_{z_file.filename}, Size: {z_file.file_size}") upload_fname = z_file.filename if "/" in upload_fname: upload_fname = f'{folder.name}_{upload_fname.partition("/")[2]}' # 直接从Zip中获取文件流,分块读取上传 with zip_file.open(z_file) as z_stream: # 创建上传会话 upload_session = ab_folder.files.create_upload_session( file_name=upload_fname, chunk_size=3072000 ).execute_query() # 基于Zip流执行分块上传 uploader = File(z_stream) upload_session.upload( uploader, chunk_uploaded=print_upload_progress ).execute_query_retry()
多线程问题解决
使用内存流后,所有操作都在内存中完成,没有磁盘IO的缓存同步延迟,因此可以完全删除flush()和time.sleep(2)代码,彻底解决多线程下的文件读取失败问题。
内容的提问来源于stack exchange,提问作者GLayton
相关产品推荐
相关产品推荐

