Response header status contentType

文件下载,指定默认名srxljl
Response.AddHeader("content-type","application/x-msdownload");
Response.AddHeader("Content-Disposition","attachment;filename=要下载的文件名.rar");

刷新页面srxljl
Response.AddHeader “REFRESH”, ”60;URL=newpath/newpage.asp”
这等同于客户机端<META>元素:
<META HTTP-EQUIV=”REFRESH”, “60;URL=newpath/newpage.asp”

页面转向srxljl
Response.Status = “302 Object Moved”
Response.Addheader “Location”, “newpath/newpage.asp”
这等同于使用Response.Redirect方法:
Response.Redirect “newpath/newpage.asp”

强制浏览器显示一个用户名/口令对话框srxljl
Response.Status= “401 Unauthorized”
Response.Addheader “WWW-Authenticate”, “BASIC”
强制浏览器显示一个用户名/口令对话框,然后使用BASIC验证把它们发送回服务器(将在本书后续部分看到验证方法)。

如何让网页不缓冲srxljl
Response.Expires = 0
Response.ExpiresAbsolute = Now() - 1
Response.Addheader "pragma","no-cache"
Response.Addheader "cache-control","private"
Response.CacheControl = "no-cache






应用实例:文件下载

做下载中文显示乱码怎么办srxljl

在网站上文件下载都是直接点击文件联接就行了,这种方法有几个弊端:
1. 有些文件不会下载会直接调用相应的程序打开该文件
2。不能隐藏实际文件地址。
3。不能够从数据库中动态读取文件名进行改名下载

下面是asp.net,c#代码:
string fileName;//文件在数据库中的名称
string dir ;//文件在服务器的物理路径(如c:\aa\ddd\wj0000222.zdo)
long size ;//文件的大小
Response.AddHeader("content-type", "application/x-msdownload;");
Response.AddHeader("Content-Disposition","attachment;filename="+fileName[自己定义的]);
Response.AddHeader("content-length", size.ToString());
Response.WriteFile(dir,0,size);

这种方法可以实现以上的目的,但是当文件名(fileName)为中文时在ie下载端显示的是乱码,有谁知道怎么解决。

我来做个总结吧   
        其实楼上的方法是可行的,但有局限性   
    
        关键在于UrlEncode这个东东,在下面不同情况下的结果是不一样的   
        1。web.config         里responseEncoding="gb2312"     
        2。web.config         里responseEncoding="utf-8"   
        使用Server.UrlEncode的话必须responseEncoding="utf-8"才会正确   
    
    
        所以不要用Server.UrlEncode,换HttpUtility.UrlEncode   
        string         s=HttpUtility.UrlEncode(System.Text.UTF8Encoding.UTF8.GetBytes("中文.txt"));   
        Response.AppendHeader("Content-Disposition",         "attachment;         filename="         +         s);   

 

百度相关搜索:response.addheader 中文乱码

参考资料:
中文显示乱码怎么办?Response.AddHeader("Content-Disposition",..(topic.youkuaiyun.com 上的更多结果)

 

Web文件的ContentType类型大全.txt

Response.AddHeader("content-type", "application/x-msdownload;");类型列表

".*"="application/octet-stream"
".001"="application/x-001"
".301"="application/x-301"
".323"="text/h323"
".906"="application/x-906"
".907"="drawing/907"
".a11"="application/x-a11"
".acp"="audio/x-mei-aac"
".ai"="application/postscript"
".aif"="audio/aiff"
".aifc"="audio/aiff"
".aiff"="audio/aiff"
".anv"="application/x-anv"
".asa"="text/asa"
".asf"="video/x-ms-asf"
".asp"="text/asp"
".asx"="video/x-ms-asf"
".au"="audio/basic"
".avi"="video/avi"
".awf"="application/vnd.adobe.workflow"
".biz"="text/xml"
".bmp"="application/x-bmp"
".bot"="application/x-bot"
".c4t"="application/x-c4t"
".c90"="application/x-c90"
".cal"="application/x-cals"
".cat"="application/vnd.ms-pki.seccat"
".cdf"="application/x-netcdf"
".cdr"="application/x-cdr"
".cel"="application/x-cel"
".cer"="application/x-x509-ca-cert"
".cg4"="application/x-g4"
".cgm"="application/x-cgm"
".cit"="application/x-cit"
".class"="java/*"
".cml"="text/xml"
".cmp"="application/x-cmp"
".cmx"="application/x-cmx"
".cot"="application/x-cot"
".crl"="application/pkix-crl"
".crt"="application/x-x509-ca-cert"
".csi"="application/x-csi"
".css"="text/css"
".cut"="application/x-cut"
".dbf"="application/x-dbf"
".dbm"="application/x-dbm"
".dbx"="application/x-dbx"
".dcd"="text/xml"
".dcx"="application/x-dcx"
".der"="application/x-x509-ca-cert"
".dgn"="application/x-dgn"
".dib"="application/x-dib"
".dll"="application/x-msdownload"
".doc"="application/msword"
".dot"="application/msword"
".drw"="application/x-drw"
".dtd"="text/xml"
".dwf"="Model/vnd.dwf"
".dwf"="application/x-dwf"
".dwg"="application/x-dwg"
".dxb"="application/x-dxb"
".dxf"="application/x-dxf"
".edn"="application/vnd.adobe.edn"
".emf"="application/x-emf"
".eml"="message/rfc822"
".ent"="text/xml"
".epi"="application/x-epi"
".eps"="application/x-ps"
".eps"="application/postscript"
".etd"="application/x-ebx"
".exe"="application/x-msdownload"
".fax"="image/fax"
".fdf"="application/vnd.fdf"
".fif"="application/fractals"
".fo"="text/xml"
".frm"="application/x-frm"
".g4"="application/x-g4"
".gbr"="application/x-gbr"
".gcd"="application/x-gcd"
".gif"="image/gif"
".gl2"="application/x-gl2"
".gp4"="application/x-gp4"
".hgl"="application/x-hgl"
".hmr"="application/x-hmr"
".hpg"="application/x-hpgl"
".hpl"="application/x-hpl"
".hqx"="application/mac-binhex40"
".hrf"="application/x-hrf"
".hta"="application/hta"
".htc"="text/x-component"
".htm"="text/html"
".html"="text/html"
".htt"="text/webviewhtml"
".htx"="text/html"
".icb"="application/x-icb"
".ico"="image/x-icon"
".ico"="application/x-ico"
".iff"="application/x-iff"
".ig4"="application/x-g4"
".igs"="application/x-igs"
".iii"="application/x-iphone"
".img"="application/x-img"
".ins"="application/x-internet-signup"
".isp"="application/x-internet-signup"
".IVF"="video/x-ivf"
".java"="java/*"
".jfif"="image/jpeg"
".jpe"="image/jpeg"
".jpe"="application/x-jpe"
".jpeg"="image/jpeg"
".jpg"="image/jpeg"
".jpg"="application/x-jpg"
".js"="application/x-javascript"
".jsp"="text/html"
".la1"="audio/x-liquid-file"
".lar"="application/x-laplayer-reg"
".latex"="application/x-latex"
".lavs"="audio/x-liquid-secure"
".lbm"="application/x-lbm"
".lmsff"="audio/x-la-lms"
".ls"="application/x-javascript"
".ltr"="application/x-ltr"
".m1v"="video/x-mpeg"
".m2v"="video/x-mpeg"
".m3u"="audio/mpegurl"
".m4e"="video/mpeg4"
".mac"="application/x-mac"
".man"="application/x-troff-man"
".math"="text/xml"
".mdb"="application/msaccess"
".mdb"="application/x-mdb"
".mfp"="application/x-shockwave-flash"
".mht"="message/rfc822"
".mhtml"="message/rfc822"
".mi"="application/x-mi"
".mid"="audio/mid"
".midi"="audio/mid"
".mil"="application/x-mil"
".mml"="text/xml"
".mnd"="audio/x-musicnet-download"
".mns"="audio/x-musicnet-stream"
".mocha"="application/x-javascript"
".movie"="video/x-sgi-movie"
".mp1"="audio/mp1"
".mp2"="audio/mp2"
".mp2v"="video/mpeg"
".mp3"="audio/mp3"
".mp4"="video/mpeg4"
".mpa"="video/x-mpg"
".mpd"="application/vnd.ms-project"
".mpe"="video/x-mpeg"
".mpeg"="video/mpg"
".mpg"="video/mpg"
".mpga"="audio/rn-mpeg"
".mpp"="application/vnd.ms-project"
".mps"="video/x-mpeg"
".mpt"="application/vnd.ms-project"
".mpv"="video/mpg"
".mpv2"="video/mpeg"
".mpw"="application/vnd.ms-project"
".mpx"="application/vnd.ms-project"
".mtx"="text/xml"
".mxp"="application/x-mmxp"
".net"="image/pnetvue"
".nrf"="application/x-nrf"
".nws"="message/rfc822"
".odc"="text/x-ms-odc"
".out"="application/x-out"
".p10"="application/pkcs10"
".p12"="application/x-pkcs12"
".p7b"="application/x-pkcs7-certificates"
".p7c"="application/pkcs7-mime"
".p7m"="application/pkcs7-mime"
".p7r"="application/x-pkcs7-certreqresp"
".p7s"="application/pkcs7-signature"
".pc5"="application/x-pc5"
".pci"="application/x-pci"
".pcl"="application/x-pcl"
".pcx"="application/x-pcx"
".pdf"="application/pdf"
".pdf"="application/pdf"
".pdx"="application/vnd.adobe.pdx"
".pfx"="application/x-pkcs12"
".pgl"="application/x-pgl"
".pic"="application/x-pic"
".pko"="application/vnd.ms-pki.pko"
".pl"="application/x-perl"
".plg"="text/html"
".pls"="audio/scpls"
".plt"="application/x-plt"
".png"="image/png"
".png"="application/x-png"
".pot"="application/vnd.ms-powerpoint"
".ppa"="application/vnd.ms-powerpoint"
".ppm"="application/x-ppm"
".pps"="application/vnd.ms-powerpoint"
".ppt"="application/vnd.ms-powerpoint"
".ppt"="application/x-ppt"
".pr"="application/x-pr"
".prf"="application/pics-rules"
".prn"="application/x-prn"
".prt"="application/x-prt"
".ps"="application/x-ps"
".ps"="application/postscript"
".ptn"="application/x-ptn"
".pwz"="application/vnd.ms-powerpoint"
".r3t"="text/vnd.rn-realtext3d"
".ra"="audio/vnd.rn-realaudio"
".ram"="audio/x-pn-realaudio"
".ras"="application/x-ras"
".rat"="application/rat-file"
".rdf"="text/xml"
".rec"="application/vnd.rn-recording"
".red"="application/x-red"
".rgb"="application/x-rgb"
".rjs"="application/vnd.rn-realsystem-rjs"
".rjt"="application/vnd.rn-realsystem-rjt"
".rlc"="application/x-rlc"
".rle"="application/x-rle"
".rm"="application/vnd.rn-realmedia"
".rmf"="application/vnd.adobe.rmf"
".rmi"="audio/mid"
".rmj"="application/vnd.rn-realsystem-rmj"
".rmm"="audio/x-pn-realaudio"
".rmp"="application/vnd.rn-rn_music_package"
".rms"="application/vnd.rn-realmedia-secure"
".rmvb"="application/vnd.rn-realmedia-vbr"
".rmx"="application/vnd.rn-realsystem-rmx"
".rnx"="application/vnd.rn-realplayer"
".rp"="image/vnd.rn-realpix"
".rpm"="audio/x-pn-realaudio-plugin"
".rsml"="application/vnd.rn-rsml"
".rt"="text/vnd.rn-realtext"
".rtf"="application/msword"
".rtf"="application/x-rtf"
".rv"="video/vnd.rn-realvideo"
".sam"="application/x-sam"
".sat"="application/x-sat"
".sdp"="application/sdp"
".sdw"="application/x-sdw"
".sit"="application/x-stuffit"
".slb"="application/x-slb"
".sld"="application/x-sld"
".slk"="drawing/x-slk"
".smi"="application/smil"
".smil"="application/smil"
".smk"="application/x-smk"
".snd"="audio/basic"
".sol"="text/plain"
".sor"="text/plain"
".spc"="application/x-pkcs7-certificates"
".spl"="application/futuresplash"
".spp"="text/xml"
".ssm"="application/streamingmedia"
".sst"="application/vnd.ms-pki.certstore"
".stl"="application/vnd.ms-pki.stl"
".stm"="text/html"
".sty"="application/x-sty"
".svg"="text/xml"
".swf"="application/x-shockwave-flash"
".tdf"="application/x-tdf"
".tg4"="application/x-tg4"
".tga"="application/x-tga"
".tif"="image/tiff"
".tif"="application/x-tif"
".tiff"="image/tiff"
".tld"="text/xml"
".top"="drawing/x-top"
".torrent"="application/x-bittorrent"
".tsd"="text/xml"
".txt"="text/plain"
".uin"="application/x-icq"
".uls"="text/iuls"
".vcf"="text/x-vcard"
".vda"="application/x-vda"
".vdx"="application/vnd.visio"
".vml"="text/xml"
".vpg"="application/x-vpeg005"
".vsd"="application/vnd.visio"
".vsd"="application/x-vsd"
".vss"="application/vnd.visio"
".vst"="application/vnd.visio"
".vst"="application/x-vst"
".vsw"="application/vnd.visio"
".vsx"="application/vnd.visio"
".vtx"="application/vnd.visio"
".vxml"="text/xml"
".wav"="audio/wav"
".wax"="audio/x-ms-wax"
".wb1"="application/x-wb1"
".wb2"="application/x-wb2"
".wb3"="application/x-wb3"
".wbmp"="image/vnd.wap.wbmp"
".wiz"="application/msword"
".wk3"="application/x-wk3"
".wk4"="application/x-wk4"
".wkq"="application/x-wkq"
".wks"="application/x-wks"
".wm"="video/x-ms-wm"
".wma"="audio/x-ms-wma"
".wmd"="application/x-ms-wmd"
".wmf"="application/x-wmf"
".wml"="text/vnd.wap.wml"
".wmv"="video/x-ms-wmv"
".wmx"="video/x-ms-wmx"
".wmz"="application/x-ms-wmz"
".wp6"="application/x-wp6"
".wpd"="application/x-wpd"
".wpg"="application/x-wpg"
".wpl"="application/vnd.ms-wpl"
".wq1"="application/x-wq1"
".wr1"="application/x-wr1"
".wri"="application/x-wri"
".wrk"="application/x-wrk"
".ws"="application/x-ws"
".ws2"="application/x-ws"
".wsc"="text/scriptlet"
".wsdl"="text/xml"
".wvx"="video/x-ms-wvx"
".xdp"="application/vnd.adobe.xdp"
".xdr"="text/xml"
".xfd"="application/vnd.adobe.xfd"
".xfdf"="application/vnd.adobe.xfdf"
".xhtml"="text/html"
".xls"="application/vnd.ms-excel"
".xls"="application/x-xls"
".xlw"="application/x-xlw"
".xml"="text/xml"
".xpl"="audio/scpls"
".xq"="text/xml"
".xql"="text/xml"
".xquery"="text/xml"
".xsd"="text/xml"
".xsl"="text/xml"
".xslt"="text/xml"
".xwd"="application/x-xwd"
".x_b"="application/x-x_b"
".x_t"="application/x-x_t"

那你看看最新的CurlTools.psm1,还有没有哪里需要优化或者修改:“function Invoke-CurlRequest { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$Url, [string]$Method = "GET", [hashtable]$Headers = @{}, [string]$Body, [string]$ContentType = "application/json", [ValidateSet("Raw", "Object")] [string]$OutputType = "Raw", [switch]$IncludeHeaders, [switch]$FollowRedirect, [int]$MaxRedirects = 10, [int]$Timeout = 0, [string]$OutputFile, [switch]$Insecure ) # 保存原始语言环境 $originalLang = $env:LANG $originalLC_ALL = $env:LC_ALL # 初始化响应对象 $response = [PSCustomObject]@{ Status = $null Content = $null Data = $null ErrorMessage = $null ErrorType = $null Url = $Url Method = $Method StatusCode = $null Headers = $null Latency = $null Size = $null Timestamp = (Get-Date) RawOutput = $null } # 计时器开始 $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() try { # 设置英文环境防止乱码 $env:LANG = 'C' $env:LC_ALL = 'C' # 构建 curl 命令参数 $curlArgs = @( $Url, "-X", $Method, "--silent", "--show-error" ) # 添加可选参数 if ($IncludeHeaders) { $curlArgs += "-i" } if ($FollowRedirect) { $curlArgs += "-L" $curlArgs += "--max-redirs" $curlArgs += $MaxRedirects } if ($Timeout -gt 0) { $curlArgs += "--connect-timeout" $curlArgs += [math]::Ceiling($Timeout/2) $curlArgs += "--max-time" $curlArgs += $Timeout } if ($OutputFile) { $curlArgs += "-o" $curlArgs += $OutputFile } if ($Insecure) { $curlArgs += "--insecure" } # 添加默认User-Agent if (-not $Headers.ContainsKey('User-Agent')) { $Headers['User-Agent'] = "PowerShell CurlTools/1.0" } # 添加内容类型头 if (-not $Headers.ContainsKey("Content-Type") -and $Body) { $Headers["Content-Type"] = $ContentType } # 添加请求头 foreach ($key in $Headers.Keys) { $curlArgs += "-H" $curlArgs += "$key`: $($Headers[$key])" } # 添加请求体 if ($Body) { $curlArgs += "-d" $curlArgs += $Body } # 修复中文乱码:使用英文日志 Write-Verbose "Executing curl command: curl $($curlArgs -join ' ')" # 执行 curl 命令 $rawOutput = if ($OutputFile) { # 直接输出到文件 curl.exe @curlArgs 2>&1 } else { # 捕获输出 $output = curl.exe @curlArgs 2>&1 if ($null -ne $output) { # 修复中文乱码:转换为UTF8 $utf8Output = $output | Out-String | ForEach-Object { [System.Text.Encoding]::UTF8.GetString( [System.Text.Encoding]::GetEncoding(0).GetBytes($_) ) } $utf8Output } } $curlExitCode = $LASTEXITCODE # 保存原始输出用于调试 $response.RawOutput = $rawOutput # 计算请求耗时 $response.Latency = $stopwatch.ElapsedMilliseconds # 处理 curl 错误 if ($curlExitCode -ne 0) { $response.Status = "Error" $response.ErrorMessage = ExtractCurlError $rawOutput $response.Content = $rawOutput $response.ErrorType = switch ($curlExitCode) { 6 { "DNSResolutionFailed" } 7 { "ConnectionFailed" } 28 { "Timeout" } default { "CurlError" } } $response.StatusCode = 0 # 明确设置为0表示网络错误 return $response } # 如果是文件输出模式 if ($OutputFile) { if (Test-Path $OutputFile) { $response.Status = "Success" # 修复中文乱码:使用英文消息 $response.Content = "Content saved to file: $OutputFile" $response.Size = (Get-Item $OutputFile).Length $response.StatusCode = 200 } else { $response.Status = "Error" $response.ErrorMessage = "File output failed: $OutputFile" $response.StatusCode = 0 } return $response } # 记录响应大小 $response.Size = $rawOutput.Length # 分离响应头和内容 $headerSection = $null $responseBody = $rawOutput $statusCode = 0 # 增强头部分离逻辑 if ($IncludeHeaders -or $rawOutput -match '^HTTP/') { # 尝试不同换行符查找头部结束位置 $lineEndings = @("`r`n`r`n", "`n`n", "`r`r") $headerEnd = $null foreach ($ending in $lineEndings) { $pos = $rawOutput.IndexOf($ending) if ($pos -gt -1) { $headerEnd = $pos break } } # 分离头部和主体 if ($null -ne $headerEnd -and $headerEnd -gt 0) { $headerSection = $rawOutput.Substring(0, $headerEnd) $responseBody = $rawOutput.Substring($headerEnd + $ending.Length) # 解析状态码 if ($headerSection -match 'HTTP/\d+\.\d+\s+(\d{3})') { $statusCode = [int]$matches[1] } # 解析响应头 $response.Headers = @{} $headerLines = $headerSection -split "`r`n|`n" foreach ($line in $headerLines) { if ($line -match '^([^:]+):\s*(.+)') { $response.Headers[$matches[1]] = $matches[2].Trim() } } } } # 设置状态码 $response.StatusCode = $statusCode # 设置响应状态 if ($statusCode -ge 400) { $response.Status = "Error" } elseif ($statusCode -eq 204) { $response.Status = "NoContent" } else { $response.Status = "Success" } # 处理空响应 if ([string]::IsNullOrWhiteSpace($responseBody) -and $statusCode -eq 204) { $response.Content = "" return $response } # 原始输出模式 if ($OutputType -eq "Raw") { $response.Content = $rawOutput return $response } # 对象模式 - 尝试解析JSON $response.Content = $responseBody try { $parsedData = $responseBody | ConvertFrom-Json -ErrorAction Stop # 智能提取嵌套数据 if ($parsedData.PSObject.Properties.Name -contains "json") { $response.Data = $parsedData.json } elseif ($parsedData.PSObject.Properties.Name -contains "data") { try { $response.Data = $parsedData.data | ConvertFrom-Json } catch { $response.Data = $parsedData.data } } else { $response.Data = $parsedData } # 如果是错误响应,提取错误信息 if ($response.Status -eq "Error") { $response.ErrorMessage = ExtractApiError $response.Data } return $response } catch { # 非JSON响应 if ($response.Status -eq "Success") { $response.Status = "NonJsonResponse" } # 智能检测内容类型 if ($responseBody -match '<!DOCTYPE html>') { $response.Headers['Content-Type'] = 'text/html' } elseif ($responseBody -match '^{') { $response.Headers['Content-Type'] = 'application/json' } elseif (-not $response.Headers['Content-Type']) { $response.Headers['Content-Type'] = 'text/plain' } # 如果是错误响应,设置错误信息 if ($response.Status -eq "Error") { $response.ErrorMessage = "Non-JSON error response" } return $response } } catch { $response.Status = "Error" $response.ErrorMessage = $_.Exception.Message $response.Content = $_.Exception.Message return $response } finally { # 恢复原始语言环境 $env:LANG = $originalLang $env:LC_ALL = $originalLC_ALL $stopwatch.Stop() } } # 辅助函数:提取curl错误信息 function ExtractCurlError([string]$content) { if ($content -match 'curl: \(\d+\) (.*)') { return $matches[1] } return $content } # 辅助函数:提取API错误信息 function ExtractApiError($responseData) { # 尝试从常见结构中提取错误信息 $errorKeys = @("error", "message", "detail", "description", "error_message") foreach ($key in $errorKeys) { if ($null -ne $responseData -and $responseData.PSObject.Properties.Name -contains $key) { $errorValue = $responseData.$key if ($errorValue -is [string]) { return $errorValue } elseif ($errorValue -is [psobject]) { return ($errorValue | Format-List | Out-String).Trim() } } } # 没有找到特定错误字段,返回整个响应 if ($null -ne $responseData) { return ($responseData | Format-List | Out-String).Trim() } return "Unknown API error" } # 导出模块函数 Export-ModuleMember -Function Invoke-CurlRequest, ExtractCurlError, ExtractApiError”
08-17
你看看这两个版本“function Invoke-CurlRequest { [CmdletBinding()] param( [Parameter(Mandatory=$true, Position=0)] [string]$Url, [string]$Method = "GET", [hashtable]$Headers = @{}, [string]$Body, [string]$ContentType = "application/json", [ValidateSet("Raw", "Object")] [string]$OutputType = "Raw", [switch]$IncludeHeaders, [switch]$FollowRedirect, [int]$MaxRedirects = 10, [int]$Timeout = 0, [string]$OutputFile, [switch]$Insecure ) # 保存原始语言环境 $originalLang = $env:LANG $originalLC_ALL = $env:LC_ALL # 初始化响应对象 $response = [PSCustomObject]@{ Status = $null Content = $null Data = $null ErrorMessage = $null ErrorType = $null Url = $Url Method = $Method StatusCode = $null Headers = $null Latency = $null Size = $null Timestamp = (Get-Date) RawOutput = $null } # 内部辅助函数:提取curl错误信息 function ExtractCurlError([string]$content) { if ($content -match 'curl: \(\d+\) (.*)') { return $matches[1] } return $content } # 内部辅助函数:提取API错误信息 function ExtractApiError($responseData) { # 尝试从常见结构中提取错误信息 $errorKeys = @("error", "message", "detail", "description", "error_message") foreach ($key in $errorKeys) { if ($null -ne $responseData -and $responseData.PSObject.Properties.Name -contains $key) { $errorValue = $responseData.$key if ($errorValue -is [string]) { return $errorValue } elseif ($errorValue -is [psobject]) { return ($errorValue | Format-List | Out-String).Trim() } } } # 没有找到特定错误字段,返回整个响应 if ($null -ne $responseData) { return ($responseData | Format-List | Out-String).Trim() } return "Unknown API error" } # 计时器开始 $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() try { # 设置英文环境防止乱码 $env:LANG = 'C' $env:LC_ALL = 'C' # URL安全处理:包含空格时添加引号 $safeUrl = if ($Url -match '\s') { "`"$Url`"" } else { $Url } # 构建 curl 命令参数 $curlArgs = @( $safeUrl, # 使用安全处理的URL "-X", $Method, "--silent", "--show-error" ) # 添加可选参数 if ($IncludeHeaders) { $curlArgs += "-i" } if ($FollowRedirect) { $curlArgs += "-L" $curlArgs += "--max-redirs" $curlArgs += $MaxRedirects } if ($Timeout -gt 0) { $curlArgs += "--connect-timeout" $curlArgs += [math]::Ceiling($Timeout/2) $curlArgs += "--max-time" $curlArgs += $Timeout } if ($Insecure) { Write-Warning "SSL certificate validation disabled - security risk!" $curlArgs += "--insecure" } # 添加默认User-Agent if (-not $Headers.ContainsKey('User-Agent')) { $Headers['User-Agent'] = "PowerShell-CurlTools/1.0" } # 添加内容类型头 if (-not $Headers.ContainsKey("Content-Type") -and $Body) { $Headers["Content-Type"] = $ContentType } # 添加请求头(安全引号处理) foreach ($key in $Headers.Keys) { $headerValue = $Headers[$key] $curlArgs += "-H" $curlArgs += "`"$key`: $headerValue`"" } # 添加请求体 if ($Body) { $curlArgs += "-d" $curlArgs += $Body } Write-Verbose "Executing curl: $($curlArgs -join ' ')" # 特殊处理文件输出 if ($OutputFile) { # 确保输出目录存在 $outputDir = Split-Path $OutputFile -Parent if (-not [string]::IsNullOrWhiteSpace($outputDir) -and -not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null } # 直接保存到文件 $fileArgs = $curlArgs + @("-o", $OutputFile) $process = Start-Process curl.exe -ArgumentList $fileArgs -NoNewWindow -PassThru -Wait $curlExitCode = $process.ExitCode if ($curlExitCode -eq 0 -and (Test-Path $OutputFile)) { $response.Status = "Success" $response.Content = "File saved successfully" $response.Size = (Get-Item $OutputFile).Length $response.StatusCode = 200 } else { $response.Status = "Error" $response.ErrorMessage = "File save failed (exit $curlExitCode)" $response.StatusCode = 0 } return $response } # 执行 curl 命令(非文件模式) $output = curl.exe @curlArgs 2>&1 $curlExitCode = $LASTEXITCODE # 处理输出编码(防乱码) $rawOutput = if ($null -ne $output) { if ($output -is [array]) { $output -join "`n" } else { $output.ToString() } } else { "" } $response.RawOutput = $rawOutput $response.Latency = $stopwatch.ElapsedMilliseconds # 处理 curl 错误 if ($curlExitCode -ne 0) { $response.Status = "Error" $response.ErrorMessage = ExtractCurlError $rawOutput $response.Content = $rawOutput $response.ErrorType = switch ($curlExitCode) { 6 { "DNSResolutionFailed" } 7 { "ConnectionFailed" } 28 { "Timeout" } default { "CurlError" } } $response.StatusCode = 0 # 明确设置为0表示网络错误 return $response } # 记录响应大小 $response.Size = $rawOutput.Length # 分离响应头和内容 $headerSection = $null $responseBody = $rawOutput $statusCode = 0 # 增强头部分离逻辑 if ($IncludeHeaders -or $rawOutput -match '^HTTP/') { # 尝试不同换行符查找头部结束位置 $lineEndings = @("`r`n`r`n", "`n`n", "`r`r") $headerEnd = $null foreach ($ending in $lineEndings) { $pos = $rawOutput.IndexOf($ending) if ($pos -gt -1) { $headerEnd = $pos break } } # 分离头部和主体 if ($null -ne $headerEnd -and $headerEnd -gt 0) { $headerSection = $rawOutput.Substring(0, $headerEnd) $responseBody = $rawOutput.Substring($headerEnd + $ending.Length) # 解析状态码 if ($headerSection -match 'HTTP/\d+\.\d+\s+(\d{3})') { $statusCode = [int]$matches[1] } # 解析响应头 $response.Headers = @{} $headerLines = $headerSection -split "`r`n|`n" foreach ($line in $headerLines) { if ($line -match '^([^:]+):\s*(.+)') { $response.Headers[$matches[1]] = $matches[2].Trim() } } } } # 设置状态码 $response.StatusCode = $statusCode # 设置响应状态 if ($statusCode -ge 400) { $response.Status = "Error" } elseif ($statusCode -eq 204) { $response.Status = "NoContent" } else { $response.Status = "Success" } # 处理空响应 if ([string]::IsNullOrWhiteSpace($responseBody) -and $statusCode -eq 204) { $response.Content = "" return $response } # 原始输出模式 if ($OutputType -eq "Raw") { $response.Content = $rawOutput return $response } # 对象模式 - 尝试解析JSON $response.Content = $responseBody try { $parsedData = $responseBody | ConvertFrom-Json -ErrorAction Stop # 智能提取嵌套数据 if ($parsedData.PSObject.Properties.Name -contains "json") { $response.Data = $parsedData.json } elseif ($parsedData.PSObject.Properties.Name -contains "data") { try { $response.Data = $parsedData.data | ConvertFrom-Json } catch { $response.Data = $parsedData.data } } else { $response.Data = $parsedData } # 如果是错误响应,提取错误信息 if ($response.Status -eq "Error") { $response.ErrorMessage = ExtractApiError $response.Data } return $response } catch { # 非JSON响应 if ($response.Status -eq "Success") { $response.Status = "NonJsonResponse" } # 智能检测内容类型 if ($responseBody -match '<!DOCTYPE html>') { $response.Headers['Content-Type'] = 'text/html' } elseif ($responseBody -match '^{') { $response.Headers['Content-Type'] = 'application/json' } elseif (-not $response.Headers['Content-Type']) { $response.Headers['Content-Type'] = 'text/plain' } # 如果是错误响应,设置错误信息 if ($response.Status -eq "Error") { $response.ErrorMessage = "Non-JSON error response" } return $response } } catch { $response.Status = "Error" $response.ErrorMessage = $_.Exception.Message $response.Content = $_.Exception.Message return $response } finally { # 恢复原始语言环境 $env:LANG = $originalLang $env:LC_ALL = $originalLC_ALL $stopwatch.Stop() } } # 导出模块函数 Export-ModuleMember -Function Invoke-CurlRequest” “function Invoke-CurlRequest { [CmdletBinding()] param( # ...现有参数保持不变... # 新增重试参数 [int]$RetryCount = 0, [int]$RetryInterval = 1, [int[]]$RetryOnStatusCodes = @(408, 429, 500, 502, 503, 504), [switch]$RetryOnTimeout ) # ...现有变量初始化... # 重试计数器 $attempt = 0 $success = $false do { $attempt++ try { # ...现有curl执行逻辑... # 检查是否需要重试 $shouldRetry = $false # 网络错误重试 (curl错误码) if ($response.ErrorType -in @("ConnectionFailed", "Timeout", "DNSResolutionFailed")) { $shouldRetry = $true Write-Verbose "网络错误重试 ($attempt/$RetryCount): $($response.ErrorType)" } # HTTP状态码重试 elseif ($response.StatusCode -in $RetryOnStatusCodes) { $shouldRetry = $true Write-Verbose "HTTP错误重试 ($attempt/$RetryCount): $($response.StatusCode)" } # 超时重试 elseif ($RetryOnTimeout -and $response.ErrorType -eq "Timeout") { $shouldRetry = $true Write-Verbose "超时重试 ($attempt/$RetryCount)" } # 成功执行 if (-not $shouldRetry) { $success = $true return $response } # 指数退避算法 if ($attempt -le $RetryCount) { $waitTime = $RetryInterval * [math]::Pow(2, $attempt - 1) $jitter = Get-Random -Minimum 0 -Maximum ($waitTime * 0.2) # 20%抖动 $totalWait = [math]::Ceiling($waitTime + $jitter) Write-Verbose "等待 ${totalWait}s 后重试 (尝试 $attempt/$RetryCount)" Start-Sleep -Seconds $totalWait } } catch { # 非预期异常处理 if ($attempt -gt $RetryCount) { $response.Status = "FatalError" $response.ErrorMessage = "重试后仍失败: $($_.Exception.Message)" return $response } # 指数退避 $waitTime = $RetryInterval * [math]::Pow(2, $attempt - 1) $jitter = Get-Random -Minimum 0 -Maximum ($waitTime * 0.2) $totalWait = [math]::Ceiling($waitTime + $jitter) Write-Verbose "异常重试 ($attempt/$RetryCount): $($_.Exception.Message)" Write-Verbose "等待 ${totalWait}s 后重试" Start-Sleep -Seconds $totalWait } } while ($attempt -le $RetryCount -and -not $success) # 所有重试失败 if (-not $success) { $response.Status = "MaxRetryExceeded" $response.ErrorMessage = "达到最大重试次数 ($RetryCount) 仍失败" } return $response } ”
08-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值