使用 Powershell 将文件上传到 Box.com
-
26-12-2019 - |
题
我正在为我的公司编写一系列 Powershell 脚本,用于在 Box.com 之间传输数据。我无法弄清楚的一件事是上传文件。Box API 需要进行多部分 POST 操作才能上传,我在这里看到了一些答案,表明我应该能够在 Powershell 中执行此操作(例如 这个)。但我似乎无法让它发挥作用。
这是我现在的代码:
Function Post-File {
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$SourcePath,
[Parameter(Mandatory=$False,Position=2)]
[string]$FolderId = ############
)
#Variables for building URIs
$baseUrl = "https://upload.box.com/api/2.0/files/content"
#Set Authorization for API requests
$headers = @{}
$AccessToken = Refresh-Tokens #A reference to another function that definitely works
$headers.Add("Authorization", "Bearer $AccessToken")
#Set POST content
$body = @{}
$body.Add("filename", [IO.File]::ReadAllBytes($SourcePath))
$body.Add("parent_id", $FolderId)
#Upload the file
Invoke-RestMethod -Uri $baseUrl -Method Post -Headers $headers -ContentType "multipart/form-data" -Body $body
}
这是我得到的回复:
{
"type":"error",
"status":400,
"code":"invalid_request_parameters",
"help_url":"http://developers.box.com/docs/#errors",
"message":"Invalid input parameters in request",
"request_id":"1764475572534bcddfe04b7"
}
我还尝试了其他一些不起作用的排列。我尝试过使用 -InFile
切换到 Invoke-RestMethod
代替 -Body
. 。我也尝试过使用 Get-Content -Raw
代替 [IO.File]::ReadAllBytes
. 。这两个都会返回一个更通用的错误: The server encountered an internal error or misconfiguration and was unable to complete your request.
.
我很确定这与我的 filename
参数不正确,但我不知道如何修复它。根据 盒子API, ,这就是curl 中的样子。有人可以帮我正确地将其翻译为 Powershell 吗?
https://upload.box.com/api/2.0/files/content \
-H "Authorization: Bearer ACCESS_TOKEN" \
-F filename=@FILE_NAME \
-F parent_id=PARENT_FOLDER_ID
解决方案
在 PowerShell 中,有几件事使得这有点棘手:
- 这
filename
参数指定文件的名称,而不是内容。 - 需要请求正文才能指定文件名和目标。
- PowerShell 对待
-InFile
和-Body
论据是相互排斥的。 - PowerShell 似乎本身不支持
multipart/form-data
帖子,根据 问题 你提到的。
由于请求正文是必需的 (1,2)——因此 -InFile
无法使用(3)——我想你可能需要自己动手 multipart/form-data
body (4) 包含必要的元数据和文件内容。 这篇博文 描述了这样做的方法。内容是一个短字符串(一条推文),但原理是相同的。
下面是我刚刚使用 Box Windows SDK 执行的上传的 Fiddler 跟踪。这显示了请求通过网络时的外观。这 $BOUNDARY
是一个任意的、唯一的字符串——GUID 效果很好。
POST https://upload.box.com/api/2.0/files/content HTTP/1.1
Authorization: Bearer $TOKEN
Content-Type: multipart/form-data; boundary="$BOUNDARY"
Host: upload.box.com
Content-Length: 2118
Accept-Encoding: gzip, deflate
--$BOUNDARY
Content-Disposition: form-data; name="file"; filename="$FILENAME"
<THE CONTENT OF $FILENAME>
--$BOUNDARY
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name="metadata"
{"parent":{"id":"$PARENT_FOLDER_ID"},"name":"$FILENAME"}
--$BOUNDARY--
这是我收到的回复:
HTTP/1.1 201 Created
Date: Mon, 14 Apr 2014 12:52:33 GMT
Server: Apache
Cache-Control: no-cache, no-store
Content-Length: 364
Connection: close
Content-Type: application/json
{"total_count":1,"entries":[{"type":"file","id":"$ID","name":"$FILENAME", ... }]}
其他提示
我可能听起来很愚蠢,但是当你这样做时会发生什么?
$body.Add("filename", $([IO.File]::ReadAllBytes($SourcePath)))