PowerShell 发 POST JSON 这件事,99% 的报错都不是 PowerShell 的锅,而是你把「请求体」和「请求头」搞混了。
我见过太多人写 Invoke-RestMethod 时,把 API Key、数据名、正文全塞进一个字符串里,然后对着 400 错误发呆。这篇就带你用云递数据的两个接口,把「推数据上去」和「把数据取下来」这两件事彻底跑通。全程占位域名 http://你的域名,密钥占位 你的APIKey,你替换成自己的就能直接跑。
PowerShell 发 POST JSON 总报错?先搞清问题出在哪
PowerShell 里发 POST 有两个常用命令:Invoke-WebRequest 和 Invoke-RestMethod。前者返回完整响应对象(含状态码、响应头),后者会自动把 JSON 响应解析成 PowerShell 对象。调试阶段我建议先用 Invoke-RestMethod,因为它对 JSON 更友好,出错时也更容易看出问题。
最常见的三个坑,你对照一下自己中的是哪个:
- Content-Type 没设对:默认情况下 PowerShell 可能发的是
application/x-www-form-urlencoded,服务端按表单解析,JSON 直接成了乱码字符串。 - 中文编码没指定:PowerShell 5.1 默认按系统 ANSI 编码发送,UTF-8 中文会变问号或乱码。
- Body 传了对象却没转 JSON:直接
-Body $obj传哈希表,某些版本会序列化成System.Collections.Hashtable字符串。
记住一条铁律:Body 必须是字符串,且是转好 JSON 的字符串;Content-Type 必须是 application/json;中文场景必须显式指定 UTF-8 字节。下面所有代码都按这条来。
云递数据接口原理:两个 POST 接口搞定存取
云递数据是一个轻量级云端数据存储与分发平台,不需要你买服务器和数据库,任何能发 HTTP 请求的语言或设备都能接入——PowerShell 自然也在列。它的核心就两个接口,一存一取,思路非常干脆:
- 推送:
POST http://你的域名/api/push.php,请求体是{"api_key":"你的APIKey","dataset":"数据名","data":要存的数据}。其中api_key也可以改用请求头X-Api-Key传递。 - 读取:
POST http://你的域名/api/pull.php,按写入顺序(FIFO)读取,取走即标记已读,不会重复下发,同时支持分页、按数据名读取。
另外还有一个兼容写法:用 ?api_key=xxx&dataset=yyy 配合纯文本请求体,可以直接存一段文本,适合老程序或简单脚本。但既然是讲 POST JSON,我们主攻 JSON 方式。
这里要特别理解「队列式已读消费」这个设计:它不是普通数据库那种「读多少次都还在」,而是像排队取号——取走了就没了。所以读取接口用错了,数据会被你亲手「读没」。后面第 6 节会专门讲怎么避免。
分步实现:用 PowerShell POST JSON 推送数据
先写一个通用的推送函数。注意 [System.Text.Encoding]::UTF8.GetBytes() 这一步,它是解决中文乱码的关键:把 JSON 字符串转成 UTF-8 字节数组再发出去,而不是让 PowerShell 自己猜编码。
function Push-CloudData {
param(
[string]$ApiKey = "你的APIKey",
[string]$Dataset = "订单队列",
[object]$Data
)
$url = "http://你的域名/api/push.php"
$body = @{
api_key = $ApiKey
dataset = $Dataset
data = $Data
} | ConvertTo-Json -Depth 10 -Compress
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body)
$resp = Invoke-RestMethod -Uri $url -Method Post `
-ContentType "application/json; charset=utf-8" `
-Body $bytes
return $resp
}
调用它推送一条对象数据,data 字段可以放对象、数组或纯文本,接口会自动规范化:
# 推送一个对象
Push-CloudData -Dataset "订单队列" -Data @{
orderId = "A20240501"
user = "张三"
amount = 199.00
time = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
}
# 推送一个数组
Push-CloudData -Dataset "设备上报" -Data @(
@{ dev = "ESP32-01"; temp = 26.5 },
@{ dev = "ESP32-02"; temp = 27.1 }
)
有一点值得注意:服务端写入时会自动计算哈希去重,内容完全相同的记录只会保留第一条。这是优点也是坑——如果你调试时反复推同一段固定文本,会以为「怎么只存了一条」,其实是去重生效了。测试时记得每次改点内容。
分步实现:用 PowerShell POST JSON 读取数据
读取接口同样是 POST。很多人会疑惑:读取为什么不用 GET?因为参数(api_key、dataset、分页)走 JSON 体更规整,也避免密钥出现在 URL 里被日志记录。读取时我习惯把 api_key 放请求头 X-Api-Key,这样请求体只留业务参数。
function Pull-CloudData {
param(
[string]$ApiKey = "你的APIKey",
[string]$Dataset = "订单队列",
[int]$Page = 1,
[int]$Size = 10
)
$url = "http://你的域名/api/pull.php"
$body = @{
dataset = $Dataset
page = $Page
size = $Size
} | ConvertTo-Json -Compress
$headers = @{ "X-Api-Key" = $ApiKey }
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body)
$resp = Invoke-RestMethod -Uri $url -Method Post `
-Headers $headers `
-ContentType "application/json; charset=utf-8" `
-Body $bytes
return $resp
}
调用并遍历取回的数据。返回结构里通常包含数据条数和条目列表,我们按通用方式遍历即可:
$result = Pull-CloudData -Dataset "订单队列" -Page 1 -Size 10
Write-Host "本次取回条数:" $result.count
foreach ($item in $result.data) {
Write-Host "已读:" $item
}
再强调一次:这一步执行完,取回的记录在云端就被标记为已读,下次再拉不会重复下发。所以如果你只是想「看看有什么」,别在生产数据名上随便跑读取脚本。稳妥做法是建一个专门的数据名做测试。
运行效果:控制台查看条数与已读状态
把推送和读取串起来跑一遍,控制台大致是这样的效果:推送几条后,先推的几条在下一次读取时被取走,控制台打印出「本次取回条数」和每一条内容;再执行一次读取,条数变成 0 或只剩没被取走的。这正是队列式消费的直观表现。
除了脚本,你也可以直接登录云递数据控制台,可视化查看每个数据名的条数、容量占用和已读状态,数据还支持下载、编辑、清空、删除。脚本负责自动化,控制台负责肉眼核对,两者搭配最省心。
下面这张表对比一下两个接口的行为,帮你建立直觉:
| 对比项 | 推送接口 push.php | 读取接口 pull.php |
|---|---|---|
| 请求方法 | POST | POST |
| 核心作用 | 写入数据到指定数据名 | 按 FIFO 顺序取出数据 |
| 是否改变数据状态 | 新增记录(相同内容去重) | 取走即标记已读 |
| 能否重复获取 | 不涉及 | 已读记录不会重复下发 |
| api_key 传递 | JSON 体或 X-Api-Key 头 | JSON 体或 X-Api-Key 头 |
| 典型场景 | 脚本/设备上报 | 消费端拉取任务 |
常见坑与注意事项:编码、请求头与限流
编码:中文乱码几乎全是没转字节数组导致的。统一用 [System.Text.Encoding]::UTF8.GetBytes($json),并在 Content-Type 里带上 charset=utf-8。PowerShell 7 默认 UTF-8,但 5.1 一定要手动处理,别偷懒。
请求头:api_key 放 JSON 体或 X-Api-Key 头都支持。我的建议是——推送时放体里方便和 dataset 一起看,读取时放头里避免明文密钥进日志。两者不要同时传冲突的值。
限流:接口有请求频率限制,别写死循环里狂刷。批量上报要加间隔,比如 Start-Sleep -Milliseconds 200,既稳又礼貌。调试时更要克制,否则被限流了你会误以为是代码问题。
去重:内容完全相同的记录只留第一条,测试数据记得每次微调。
会员:新用户注册即赠送 3 天会员免费试用;正式会员月卡 19 元、年卡 99 元,采用卡密充值(YK 开头月卡、NK 开头年卡),多张可叠加、到期顺延。会员到期后数据保留不删除,只是暂停推送和读取,续费即恢复。另外邀请好友注册,好友用卡密开月卡推荐人得 10 天,开年卡得 30 天(天数以后台配置为准),每次续费都奖、自动到账。
常见问题
PowerShell POST JSON 时中文乱码怎么解决?
核心是三步:JSON 字符串用 UTF-8 转成字节数组 [System.Text.Encoding]::UTF8.GetBytes($json) 再作为 Body;Content-Type 写成 application/json; charset=utf-8;PowerShell 5.1 下不要依赖默认编码。三步做齐,中文就不会乱。
api_key 放在 JSON 体里和放在请求头有什么区别?
功能上两者都支持,接口都能识别。区别在于:放体里便于和 dataset、data 一起查看和调试;放 X-Api-Key 请求头里则不会出现在请求体或 URL 中,更不容易被日志记录,读取接口我推荐用请求头方式。注意同一个请求不要同时传两个冲突的值。
读取接口取走数据后还能再读一次吗?
不能。读取接口按写入顺序(FIFO)消费,取走即标记已读,不会重复下发。这正是它适合做任务队列的原因。如果你需要保留原始数据,请在推送端另存一份,或读取后自行落库。
PowerShell 推送的数据支持数组和对象吗?
支持。data 字段可以放对象、数组或纯文本,接口会自动规范化处理。用 ConvertTo-Json -Depth 10 保证嵌套结构完整序列化即可,注意内容完全相同的记录会被去重,只保留第一条。
会员到期后已推送的数据会被删除吗?
不会。会员到期后数据保留不删除,只是暂停推送和读取功能,续费后即恢复使用。所以不用担心到期丢数据,按时续费或提前用卡密叠加即可。
开始使用
本文的代码示例都可以直接在云递数据上运行:注册后即可获得专属 APIKey,在 开发文档 中查看推送、读取接口的完整说明;需要长期使用可以在 会员中心 用卡密开通月卡或年卡;更多实战内容可以浏览技术博客的其他文章。