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

Java调用Microsoft Graph API创建OneDrive上传会话报错,求MP4上传指南

错误原因与修复

你遇到的Specified HTTP method is not allowed for the request target错误,核心原因是创建上传会话的HTTP方法错误。根据Microsoft Graph API规范,创建上传会话必须使用POST方法,而非你代码中的PUT。

修正后的createUploadSession方法:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public String createUploadSession(String userId, String fileName) throws Exception {
    String url = "https://graph.microsoft.com/v1.0/users/" + userId + "/drive/root:/" + fileName + ":/createUploadSession";
    HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
    connection.setRequestMethod("POST"); // 修正为POST方法
    connection.setRequestProperty("Authorization", "Bearer " + accessToken);
    connection.setRequestProperty("Content-Type", "application/json");
    connection.setDoOutput(true);

    // 指定文件冲突时的处理行为
    String jsonPayload = "{\"item\": {\"@microsoft.graph.conflictBehavior\": \"rename\"}}";
    try (OutputStream os = connection.getOutputStream()) {
        os.write(jsonPayload.getBytes(StandardCharsets.UTF_8));
    }

    // 处理响应
    if (connection.getResponseCode() >= 200 && connection.getResponseCode() < 300) {
        String response = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(response);
        return jsonNode.get("uploadUrl").asText();
    } else {
        String error = new String(connection.getErrorStream().readAllBytes(), StandardCharsets.UTF_8);
        throw new RuntimeException("创建上传会话失败: " + error);
    }
}

OneDrive上传MP4文件完整指南

1. 前置准备

  • 权限配置:确保应用已申请以下权限之一(根据业务场景选择):
    • Files.ReadWrite:用户授权后访问自身OneDrive文件
    • Files.ReadWrite.All:访问所有用户的OneDrive文件(需管理员同意)
  • 获取AccessToken:通过Microsoft Identity Platform的OAuth2授权流程,获取包含上述权限的AccessToken。

2. 创建上传会话

使用上述修正后的createUploadSession方法,获取分块专用的uploadUrl。该URL无需重复携带AccessToken,可用于后续所有分块上传请求。

3. 分块上传MP4文件

MP4文件通常体积较大,需采用分块上传。推荐分块大小为32MB(范围在5MB-60MB之间均可),以下是分块上传的实现代码:

import java.io.File;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public void uploadFileInChunks(String uploadUrl, File mp4File) throws Exception {
    final int CHUNK_SIZE = 32 * 1024 * 1024; // 32MB分块大小
    long fileSize = mp4File.length();
    long uploadedBytes = 0;

    try (RandomAccessFile raf = new RandomAccessFile(mp4File, "r")) {
        while (uploadedBytes < fileSize) {
            long bytesToRead = Math.min(CHUNK_SIZE, fileSize - uploadedBytes);
            byte[] chunk = new byte[(int) bytesToRead];
            raf.read(chunk);

            // 构建分块请求
            HttpURLConnection connection = (HttpURLConnection) new URL(uploadUrl).openConnection();
            connection.setRequestMethod("PUT");
            // 设置Content-Range头,格式为 bytes 起始索引-结束索引/总大小
            String contentRange = String.format("bytes %d-%d/%d", uploadedBytes, uploadedBytes + bytesToRead - 1, fileSize);
            connection.setRequestProperty("Content-Range", contentRange);
            connection.setDoOutput(true);

            // 发送分块数据
            try (OutputStream os = connection.getOutputStream()) {
                os.write(chunk);
            }

            // 处理响应
            int responseCode = connection.getResponseCode();
            if (responseCode == 200 || responseCode == 201) {
                // 全部分块上传完成,返回文件信息
                String response = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
                System.out.println("文件上传完成: " + response);
                break;
            } else if (responseCode == 202) {
                // 当前分块上传成功,继续下一块
                uploadedBytes += bytesToRead;
                System.out.println("已上传: " + uploadedBytes + "/" + fileSize + " bytes");
            } else {
                String error = new String(connection.getErrorStream().readAllBytes(), StandardCharsets.UTF_8);
                throw new RuntimeException("分块上传失败: " + error);
            }
        }
    }
}

4. 完整调用示例

public static void main(String[] args) {
    try {
        String accessToken = "你的有效AccessToken";
        String userId = "tranduongtruong1623_gmail.com#EXT#@tranduongtruong1623gmail.onmicrosoft.com";
        String fileName = "uploaded_video.mp4";
        File mp4File = new File("本地MP4文件的绝对路径");

        OneDriveService service = new OneDriveService(accessToken); // 假设构造方法传入accessToken
        String uploadUrl = service.createUploadSession(userId, fileName);
        service.uploadFileInChunks(uploadUrl, mp4File);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

关键注意事项

  • 分块大小不可超过60MB,否则API会返回错误。
  • 若上传中断,可直接复用uploadUrl继续上传未完成的分块,无需重新创建会话。
  • Content-Range的索引从0开始,需确保起始、结束索引与已上传字节数严格对应。

内容的提问来源于stack exchange,提问作者Dia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:17:02