Téléchargez un fichier sur Box.com à l'aide de Powershell
-
26-12-2019 - |
Question
Je travaille sur une série de scripts Powershell que mon entreprise pourra utiliser pour transférer des données vers et depuis Box.com.La seule chose que je n'arrive pas à comprendre, c'est le téléchargement de fichiers.L'API Box nécessite une opération POST en plusieurs parties pour les téléchargements, et j'ai vu quelques réponses ici sur SO indiquant que je devrais pouvoir le faire dans Powershell (comme celui-ci).Mais je n'arrive pas à le faire fonctionner.
Voici le code que j'ai en ce moment :
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
}
Voici la réponse que je reçois :
{
"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"
}
J'ai également essayé quelques autres permutations qui ne fonctionnent pas.J'ai essayé d'utiliser le -InFile
entrer Invoke-RestMethod
au lieu de -Body
.J'ai aussi essayé d'utiliser Get-Content -Raw
au lieu de [IO.File]::ReadAllBytes
.Les deux renvoient une erreur plus générique : The server encountered an internal error or misconfiguration and was unable to complete your request.
.
Je suis presque sûr que cela a quelque chose à voir avec mon filename
le paramètre n'est pas correct, mais je ne sais pas comment le corriger.Selon le API de boîte, voici à quoi cela devrait ressembler en curl.Quelqu'un peut-il m'aider à traduire correctement ceci pour 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
La solution
Il y a quelques éléments qui rendent cela un peu délicat dans PowerShell :
- Le
filename
Le paramètre spécifie le nom du fichier, pas son contenu. - Un corps de requête est requis afin de spécifier le nom du fichier et la destination.
- Gâteries PowerShell
-InFile
et-Body
arguments comme s’excluant mutuellement. - PowerShell ne semble pas prendre en charge nativement
multipart/form-data
POST, selon le question que vous avez référencé.
Puisque le corps de la requête est requis (1,2) -- et donc -InFile
ne peut pas être utilisé (3) -- je pense que vous devrez peut-être rouler le vôtre multipart/form-data
corps (4) qui contient les métadonnées nécessaires et le contenu du fichier. Ce billet de blog décrit une méthode pour le faire.Le contenu y est une courte chaîne (un tweet) mais le principe est le même.
Vous trouverez ci-dessous une trace Fiddler d'un téléchargement que je viens d'effectuer à l'aide du SDK Box Windows.Cela montre à quoi devrait ressembler la demande lorsqu'elle traverse le réseau.Le $BOUNDARY
est une chaîne arbitraire et unique – un GUID fonctionne très bien.
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--
Voici la réponse que j'ai reçue :
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", ... }]}
Autres conseils
Je peux paraître stupide, mais que se passe-t-il lorsque vous faites cela ?
$body.Add("filename", $([IO.File]::ReadAllBytes($SourcePath)))