Загрузите файл на Box.com с помощью Powershell.
-
26-12-2019 - |
Вопрос
Я работаю над серией сценариев Powershell, которые моя компания будет использовать для передачи данных на Box.com и обратно.Единственное, чего я не могу понять, так это загрузки файлов.API Box требует многочастной операции POST для загрузки, и я видел несколько ответов здесь на SO, указывающих, что я должен иметь возможность сделать это в 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
POST, согласно вопрос на что вы ссылались.
Поскольку требуется тело запроса (1,2) - и, следовательно, -InFile
невозможно использовать (3) – думаю, вам, возможно, придется свернуть свой собственный multipart/form-data
тело (4), содержащее необходимые метаданные и содержимое файла. Этот пост в блоге описывает способ сделать это.Содержимое там — короткая строка (твит), но принцип тот же.
Ниже приведена трассировка Fiddler только что выполненной загрузки с использованием Box Windows SDK.Это показывает, как должен выглядеть запрос при передаче по сети.А $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)))