使用PowerShell的[System.Net.Http.HttpClient]发送multipart/form-data遇400错误
问题:自定义WebEx交互函数无法处理multipart/form-data请求
我正在开发用于与WebEx API交互的自定义函数Invoke-WebExRequest,该函数大部分功能正常,但无法处理multipart/form-data类型的数据。
已成功的场景
1. 用Invoke-WebRequest手动构造multipart请求体
手动构造纯文本格式的请求体,指定包含边界的-ContentType参数后,使用Invoke-WebRequest可成功发送multipart/form-data数据:
$GUID = New-Guid $Body = @" ------------$($GUID)------------ Content-Disposition: form-data; name="roomId" $($RoomId) ------------$($GUID)------------ Content-Disposition: form-data; name="html" <h3>Testing...</h3> ------------$($GUID)------------ "@ $ContentType = "multipart/form-data; boundary=----------$($GUID)------------" $Result = Invoke-WebRequest -Headers $Headers ` -Uri $URI ` -Method 'Post' ` -Body $Body ` -ContentType $ContentType $GUID = New-Guid
2. 用[System.Net.Http.HttpClient]发送JSON请求
仅发送JSON格式文本消息时,[System.Net.Http.HttpClient]能正常工作:
$Body = @{ "roomId" = $RoomId "text" = 'This is just a test' } $Client = [System.Net.Http.HttpClient]::new() $Content = [System.Net.Http.HttpRequestMessage]::new() $Content.Headers.Add('Authorization',"Bearer $($Token)") $Content.RequestUri = $URI $Content.Method = 'Post' $UTF8 = [System.Text.Encoding]::UTF8 $Body = $($Body | ConvertTo-Json) $Body = [System.Net.Http.StringContent]::new($Body,$UTF8,'application/json') $Content.Content = $Body $Client.SendAsync($Content).GetAwaiter().GetResult()
遇到的问题
尝试用[System.Net.Http.HttpClient]发送multipart/form-data时,代码无报错但返回400 - BadRequest,尝试的代码如下:
$Body = @" ------------$($GUID)------------ Content-Disposition: form-data; name="roomId" $($RoomId) ------------$($GUID)------------ Content-Disposition: form-data; name="html" <h3>Testing with [System.Net.Http.HttpClient]</h3> ------------$($GUID)------------ "@ $Client = [System.Net.Http.HttpClient]::new() $Content = [System.Net.Http.HttpRequestMessage]::new() $Content.Headers.Add('Authorization',"Bearer $($Token)") $Content.RequestUri = $URI $Content.Method = 'Post' $UTF8 = [System.Text.Encoding]::UTF8 $Body = [System.Net.Http.StringContent]::new($Body,$UTF8,'multipart/form-data') $Content.Content = $Body $Client.SendAsync($Content).GetAwaiter().GetResult()
解决方案
问题出在手动构造multipart请求体后,用StringContent传递时未正确设置ContentType的边界参数,且HttpClient提供了专门的MultipartFormDataContent类处理这类请求,无需手动拼接字符串,可避免格式错误:
$Client = [System.Net.Http.HttpClient]::new() $Content = [System.Net.Http.MultipartFormDataContent]::new() # 添加roomId字段 $roomIdContent = [System.Net.Http.StringContent]::new($RoomId) $Content.Add($roomIdContent, "roomId") # 添加html字段 $htmlContent = [System.Net.Http.StringContent]::new("<h3>Testing with [System.Net.Http.HttpClient]</h3>") $Content.Add($htmlContent, "html") # 创建请求消息 $request = [System.Net.Http.HttpRequestMessage]::new([System.Net.Http.HttpMethod]::Post, $URI) $request.Headers.Add('Authorization', "Bearer $($Token)") $request.Content = $Content # 发送请求 $response = $Client.SendAsync($request).GetAwaiter().GetResult() $response.EnsureSuccessStatusCode() # 自动抛出非2xx状态码的异常
说明
MultipartFormDataContent会自动生成正确的边界值并设置到ContentType头中,避免手动拼接时可能出现的换行、分隔符格式错误;- 若需上传文件,只需用
ByteArrayContent或StreamContent包装文件内容,再添加到MultipartFormDataContent即可。
内容的提问来源于stack exchange,提问作者James W
相关产品推荐
相关产品推荐

