You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用SharePoint API分块上传遇serverRelativeUrl参数错误

SharePoint分块上传API错误-2147024809修复方案

问题核心原因

你遇到的serverRelativeUrl参数错误,主要由三个问题导致:

  • 服务器相对路径格式不完整且错误提前编码
  • 对整个API请求URL进行了不必要的全编码,导致SharePoint无法识别API路径
  • 文件偏移量(fileOffset)计算逻辑错误

具体修复步骤

1. 修正服务器相对路径格式

getfilebyserverrelativeurl要求的参数是完整的站点级服务器相对路径,格式应为:

/sites/{site_name}/Shared Documents/{folder_name}/{file_name}

注意:

  • 不要提前对路径进行URL编码(比如不要把空格换成%20),SharePoint会自动处理路径中的特殊字符
  • 如果是根站点(非/sites子站点),路径开头去掉/sites/{site_name}即可

2. 禁止对整个API URL编码

你代码中url = urllib.parse.quote(file_url)是错误操作,会把API路径中的/、(等字符编码成%2F、%28,导致SharePoint无法识别正确的API端点。直接使用拼接好的file_url作为请求路径即可。

3. 修正fileOffset计算逻辑

  • startupload:不需要指定fileOffset,接口会自动处理第一块数据
  • continueupload:fileOffset是已上传的总字节数,即CHUNK_SIZE * (chunk_count - 1)(比如第2块的offset是1*CHUNK_SIZE)
  • finishupload:fileOffset必须等于文件总大小,无论最后一块是否填满CHUNK_SIZE

4. 修正分块计数逻辑

用math.ceil(file_size / CHUNK_SIZE)计算总块数,避免浮点数导致循环次数错误。

修改后的完整代码

import os
import uuid
import http.client
import math

CHUNK_SIZE = 10 * 1024 * 1024  # 10MB分块,可根据需求调整
SHAREPOINT_HOST = "your-tenant.sharepoint.com"  # 替换为你的SharePoint域名

def uploadFile(bearer_token: str, tenant_name: str, site_name: str, folder_name: str, file_name: str) -> str:
    with open(file_name, "rb") as file:
        file_size = os.stat(file_name).st_size    
        big_file = file_size > CHUNK_SIZE
        if big_file:
            headers = {
                'Authorization': f'Bearer {bearer_token}',
                'Accept': 'application/json;odata=verbose',
                'Content-Type': 'application/octet-stream'
            }        
                       
            upload_id = uuid.uuid4()
            chunk_count = 1
            total_chunks = math.ceil(file_size / CHUNK_SIZE)
            continue_upload = True
            
            # 构建正确的服务器相对路径
            server_relative_url = f"/sites/{site_name}/Shared Documents/{folder_name}/{os.path.basename(file_name)}"

            while continue_upload:
                big_file_chunk = file.read(CHUNK_SIZE)
                chunk_length = len(big_file_chunk)
                
                if chunk_count == total_chunks:  # 最后一块,执行finishupload
                    file_offset = file_size
                    api_path = f"/sites/{site_name}/_api/web/getfilebyserverrelativeurl('{server_relative_url}')/finishupload(uploadId=guid'{upload_id}',fileOffset={file_offset})"
                    continue_upload = False
                elif chunk_count == 1:  # 第一块,执行startupload
                    api_path = f"/sites/{site_name}/_api/web/getfilebyserverrelativeurl('{server_relative_url}')/startupload(uploadId=guid'{upload_id}')"
                else:  # 中间块,执行continueupload
                    file_offset = CHUNK_SIZE * (chunk_count - 1)
                    api_path = f"/sites/{site_name}/_api/web/getfilebyserverrelativeurl('{server_relative_url}')/continueupload(uploadId=guid'{upload_id}',fileOffset={file_offset})"
             
                # 直接使用api_path,不要编码整个URL
                conn = http.client.HTTPSConnection(SHAREPOINT_HOST)
                conn.request("POST", api_path, big_file_chunk, headers)
                resp = conn.getresponse()
                resp_content = resp.read()
                print(chunk_count, " -- ", resp_content)
                
                # 检查响应状态码,非200/201则抛出异常或处理
                if resp.status not in (200, 201, 202):
                    raise Exception(f"Upload failed at chunk {chunk_count}: {resp_content.decode('utf-8')}")
                
                chunk_count += 1

            return resp_content.decode("utf-8")

额外注意事项

  • 确保SHAREPOINT_HOST是你的租户域名(比如contoso.sharepoint.com),不要包含https://
  • 分块大小建议设置为10MB到100MB之间,过大可能导致请求超时
  • 每次请求后检查响应状态码,及时捕获上传失败的情况

内容的提问来源于stack exchange,提问作者d.rat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:07:50