使用Python API从Databricks DBFS下载大文件的问题
使用Databricks DBFS API分片下载大文件的正确姿势
你遇到的两个核心问题:循环拉取只得到520KB文件、分片方案不够优雅,其实都是对DBFS API的参数处理和返回数据解码理解不到位导致的,下面给你拆解正确的实现方式:
为什么你的循环只拿到520KB?
大概率是这两个原因:
- 没有对API返回的
data字段做Base64解码:DBFS API返回的文件内容是Base64编码后的字符串,直接拼接的话,实际字节数会比预期少(甚至因编码截断导致有效内容大幅缩水) - 没有正确计算最后一片的长度:当剩余文件大小不足1MB时,仍指定
length=1MB,API会返回空数据或截断内容
正确的分片下载实现步骤
DBFS下载确实不需要像上传那样的句柄会话,直接通过offset和length参数循环拉取即可,这是API设计的正常逻辑,按以下步骤来:
- 先获取文件总大小:调用
dbfs/get-status接口拿到文件总字节数,用来控制循环终止条件 - 分片拉取并解码:每次循环计算当前的
offset和length(单次最大1MB),拉取后对data做Base64解码,写入本地文件 - 更新偏移量:每次拉取完成后,将
offset累加当前拉取的字节数,直到偏移量超过文件总大小
代码示例(Python)
import requests import base64 import os # 替换为你的实际配置 DATABRICKS_HOST = "https://<你的Databricks实例地址>" API_TOKEN = "<你的Databricks API Token>" DBFS_FILE_PATH = "/dbfs/路径/到大文件" LOCAL_SAVE_PATH = "./本地保存的文件名" # 第一步:获取文件总大小 status_req = requests.post( f"{DATABRICKS_HOST}/api/2.0/dbfs/get-status", headers={"Authorization": f"Bearer {API_TOKEN}"}, json={"path": DBFS_FILE_PATH} ) status_req.raise_for_status() total_size = status_req.json()["file_size"] # 第二步:分片下载 chunk_size = 1048576 # 1MB,API单次最大限制 current_offset = 0 with open(LOCAL_SAVE_PATH, "wb") as local_file: while current_offset < total_size: # 计算当前分片的实际长度(最后一片可能小于1MB) fetch_length = min(chunk_size, total_size - current_offset) # 调用DBFS read接口 read_req = requests.post( f"{DATABRICKS_HOST}/api/2.0/dbfs/read", headers={"Authorization": f"Bearer {API_TOKEN}"}, json={ "path": DBFS_FILE_PATH, "offset": current_offset, "length": fetch_length } ) read_req.raise_for_status() response_data = read_req.json() # 解码Base64数据并写入文件 file_content = base64.b64decode(response_data["data"]) local_file.write(file_content) # 更新偏移量 current_offset += fetch_length
关键注意事项
- Base64解码必须做:这是导致你文件大小异常的核心原因,API返回的
data不是原始字节,一定要解码后再写入 - 控制单次拉取长度:不要超过1MB的API限制,否则会返回错误
- 异常处理:示例中用
raise_for_status()捕获请求错误,实际生产环境可以根据需要增加重试逻辑 - 不用纠结上传的句柄机制:DBFS上传用句柄是为了分块上传时维护会话状态,下载是只读操作,直接用偏移量定位更高效,这是API的合理设计
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

