使用Graph API上传IPA至Intune时触发Bad Request 400错误
问题
通过PowerShell调用Graph API在Intune中创建iOS LOB(.ipa)应用时,应用可正常创建,但调用第二个Invoke-RestMethod上传IPA文件时,持续触发Bad Request 400错误。尝试了字节流、字符串等多种上传方式均无效。
相关代码片段:
$tenantId = "XXXXXXXXXXXXXXXXXXX" $clientId = "XXXXXXXXXXXXXXXXXXXX" $clientSecret = "XXXXXXXXXXXXXXXXXXX" $appPath = "./Path to .ipa file" ## Relative Path $resource = "https://graph.microsoft.com/" $authUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" $authBody = @{ client_id = $clientId client_secret = $clientSecret scope = "https://graph.microsoft.com/.default" grant_type = "client_credentials" } $tkResponse = Invoke-RestMethod -Method Post -Uri $authUrl -ContentType "application/x-www-form-urlencoded" -Body $authBody $origToken = $tkResponse.access_token $initialheaders = @{ Authorization = "Bearer $origToken" "Content-Type" = "application/json" } $body = @{ "@odata.type" = "#microsoft.graph.iosLobApp" displayName = "Test" bundleId = "self.test.sample.app" buildNumber = "1.0.0" versionNumber = "1.0.0" description = "Test description" publisher = "Test Publisher" fileName = "Test.ipa" committedContentVersion = "1" informationUrl = "https://yourappwebsite.com" privacyInformationUrl = "https://yourappwebsite.com/privacy" minimumSupportedOperatingSystem = @{ v8_0 = $true } applicableDeviceType = @{ iPad = $true iPhoneAndIPod = $true } } $mobJson = $body | ConvertTo-Json -Depth 10 $graphApiUrl = "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps" try{ $response = Invoke-RestMethod -Method Post -Uri $graphApiUrl -Headers $initialheaders -Body $mobJson -ErrorAction Stop -verbose $applicationId = $response.id } catch { Write-Host "$($_.Exception.Response.StatusCode)" } $fileUpUrl = "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps/$applicationId/contentVersions/1/files" $fContent = [System.IO.File]::ReadAllBytes($appPath) $baseContent = [Convert]::ToBase64String($fContent) $contheaders = @{ Authorization = "Bearer $origToken" "Content-Type" = "application/octet-stream" } $uploadBody = @{ "@odata.type" = "#microsoft.graph.mobileAppContentFile" name = (Get-Item $appPath).Name sizeInBytes = (Get-Item $appPath).Length versionCode = "1.0.0" versionName = "Version Name" contentBytes = $baseContent } | ConvertTo-Json try{ ## ERROR COMES FROM BELOW INVOKE METHOD ## $uploadResp = Invoke-RestMethod -Uri $fileUpUrl -Method Post -Headers $contheaders -Body $uploadBody -Verbose } catch { $error = $_.Exception }
错误详情:
2024-12-23T18:16:34.9342611Z Error uploading IPA file: The remote server returned an error: (400) Bad Request. 2024-12-23T18:16:34.9370301Z System.Net.WebException: The remote server returned an error: (400) Bad Request. 2024-12-23T18:16:34.9372124Z at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request) 2024-12-23T18:16:34.9392176Z at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord() 2024-12-23T18:16:34.9404004Z Error11: System.Net.WebException: The remote server returned an error: (400) Bad Request. 2024-12-23T18:16:34.9404570Z at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request) 2024-12-23T18:16:34.9405060Z at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord() 2024-12-23T18:16:34.9406974Z Error11 Message: System.Net.WebException: The remote server returned an error: (400) Bad Request. 2024-12-23T18:16:34.9407299Z at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request) 2024-12-23T18:16:34.9408070Z at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord().Message
解决方案
错误核心在于上传IPA文件的流程不符合Graph API要求,直接将大文件转成Base64放入请求体不仅会导致请求过大,还违背了API设计逻辑。正确上传流程分为三步:
1. 创建空的mobileAppContentFile条目
先上传文件元数据(不含实际内容),请求头使用application/json:
$fileUpUrl = "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps/$applicationId/contentVersions/1/files" $contheaders = @{ Authorization = "Bearer $origToken" "Content-Type" = "application/json" } # 仅上传元数据,不包含contentBytes $uploadBody = @{ "@odata.type" = "#microsoft.graph.mobileAppContentFile" name = (Get-Item $appPath).Name sizeInBytes = (Get-Item $appPath).Length versionCode = "1.0.0" versionName = "Version Name" } | ConvertTo-Json -Depth 10 try{ $uploadResp = Invoke-RestMethod -Uri $fileUpUrl -Method Post -Headers $contheaders -Body $uploadBody -Verbose $fileId = $uploadResp.id } catch { Write-Host "创建文件元数据失败: $($_.Exception.Response.StatusCode)" $error = $_.Exception }
2. 获取上传会话URL
通过已创建的文件ID获取专用上传会话:
$uploadSessionUrl = "https://graph.microsoft.com/v1.0/deviceAppManagement/mobileApps/$applicationId/contentVersions/1/files/$fileId/createUploadSession" try{ $sessionResp = Invoke-RestMethod -Uri $uploadSessionUrl -Method Post -Headers $contheaders -Body "{}" -Verbose $uploadUrl = $sessionResp.uploadUrl } catch { Write-Host "获取上传会话失败: $($_.Exception.Response.StatusCode)" $error = $_.Exception }
3. 上传文件字节流到会话URL
使用PUT请求直接上传文件字节流,请求头使用application/octet-stream:
$fContent = [System.IO.File]::ReadAllBytes($appPath) $uploadHeaders = @{ "Content-Type" = "application/octet-stream" } try{ Invoke-RestMethod -Uri $uploadUrl -Method Put -Headers $uploadHeaders -Body $fContent -Verbose Write-Host "文件上传成功" } catch { Write-Host "上传文件失败: $($_.Exception.Response.StatusCode)" $error = $_.Exception }
额外注意事项
- 确保应用注册拥有
DeviceManagementApps.ReadWrite.All权限,且已完成管理员同意授权 - 若IPA文件超过4MB,建议使用分块上传,通过
Content-Range头分段传输 - 检查
bundleId、buildNumber、versionNumber是否与IPA文件内的实际信息完全匹配,不匹配也会导致上传失败
内容的提问来源于stack exchange,提问作者Amit Saxena
相关产品推荐
相关产品推荐

