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
相关产品推荐
相关产品推荐

