You are not logged in.

Announcement

 Téléchargez la dernière version stable de GLPI      -     Et vous, que pouvez vous faire pour le projet GLPI ? :  Contribuer
 Download last stable version of GLPI                      -     What can you do for GLPI ? :  Contribute

#1 2018-11-27 19:05:12

BoSaGa
Member
Registered: 2018-11-21
Posts: 10

[SOLVED] Uploading files to GLPI server using C# with RestSharp

Hi, i'm trying to POST a Document in GLPI through API REST.

here is what i'm doing :

        private void button11_Click(object sender, EventArgs e)
        {
            using (var client = new HttpClient())
            {
                using (var content = new MultipartFormDataContent())
                {
                    var rcontent = string.Empty;
                    // HEADERS (URL + Access Tokens)
                    //

                    //string _ContentType = "multipart/form-data";
                    string _Uri = Properties.Settings.Default.GLPI_URL + "/Document/";

                    client.BaseAddress = new Uri(_Uri);
                    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(_ContentType));
                    client.DefaultRequestHeaders.Add("Session-Token", Properties.Settings.Default.GLPI_SESSION_TOKEN);
                    client.DefaultRequestHeaders.Add("App-Token", Properties.Settings.Default.GLPI_APP_TOKEN);

                    // JSON Content (input string array with file uploaded informations)
                    //

                    JSON_C.DocumentAdder JSONContent = new JSON_C.DocumentAdder();
                    JSONContent.name = "sth";
                    JSONContent._filename = filebytes;
                    HttpContent _JSONContent = new StringContent("uploadManifest={\"input\": " + JsonConvert.SerializeObject(JSONContent).ToString() + "}", Encoding.UTF8, "application/json");
                    content.Add(_JSONContent);

                    // File Content in bytes
                    //
                    var fileContent = new ByteArrayContent(filebytes);
                    fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("_filename") { FileName = filepath };
                    //fileContent.ReadAsByteArrayAsync();
                    content.Add(fileContent);

                    // Request
                    //
                    HttpResponseMessage reponse;
                    var _Method = new HttpMethod("POST");
                    reponse = client.PostAsync(_Uri, content).Result;

                    // Request response
                    //
                    rcontent = reponse.Content.ReadAsStringAsync().Result;

                    textBox2.Text = reponse.ToString() + Environment.NewLine + rcontent.ToString();
                }
            }
        }

But, this is what i got in response :

StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Connection: close
  Cache-Control: no-store, must-revalidate, no-cache
  Date: Mon, 26 Nov 2018 12:50:09 GMT
  Server: Apache/2.4.29
  Server: (Ubuntu)
  Content-Length: 61
  Content-Type: application/json; charset=UTF-8
  Expires: Mon, 26 Jul 1997 05:00:00 GMT
}

With :

["ERROR_UPLOAD_FILE_TOO_BIG_POST_MAX_SIZE","The file seems too big"]

The file i'm trying to upload is 592bytes heavy ! Max overall limit in one request is 2Mo.
And "post_max_size" in php.ini is 8m, same result after i changed it to "0" (for no limit at all). (/etc/php/7.2/apache2/php.ini)

I've tried multiple different assiociations, but same result.

I've tried JSON input string array with ( "filename" + string ) or ("_filename" + string) (like documentation says), or even ( "_filename" + bytes[] array)


Anyone to help ?

Last edited by BoSaGa (2018-12-02 09:46:43)

Offline

#2 2018-11-30 14:21:23

BSG
Member
Registered: 2018-11-28
Posts: 4

Re: [SOLVED] Uploading files to GLPI server using C# with RestSharp

Je me permet de bump ce post, j'ai vraiment besoin d'une aide.

Offline

#3 2018-12-01 22:42:09

BoSaGa
Member
Registered: 2018-11-21
Posts: 10

Re: [SOLVED] Uploading files to GLPI server using C# with RestSharp

For those interested, i finally managed to succeed using RestSharp, which is quite a fantastic tool btw, simple but powerfull :

Pour ceux que ça intéresse, j'y suis finalement parvenu en utilisant RestSharp qui est d'ailleurs en passant assez génial pour sa simplicité apparente tout en gardant des fonctionnalités puissantes :

// Upload

var RSClient = new RestClient(Properties.Settings.Default.GLPI_URL);

var request = new RestRequest("Document", Method.POST);
request.AddHeader("Session-Token", Properties.Settings.Default.GLPI_SESSION_TOKEN);
request.AddHeader("App-Token", Properties.Settings.Default.GLPI_APP_TOKEN);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "multipart/form-data");
request.AddQueryParameter("uploadManifest", "{\"input\": {\"name\": \"UploadFileTest\", \"_filename\": \"GiletsJaunes.jpg\"}}");
request.AddFile("test", @"C:\path\to\File.jpg");

IRestResponse response = RSClient.Execute(request);
var content = response.Content;

textBox2.Text = textBox2.Text + Environment.NewLine + content;

Details :

- I couldn't put a serialised object after "AddQueryParameter", even if i converted it "ToString()", so i had to type it manually. You can use variables ofc, but you have to keep the " right before and after those variables.
- I could not Authenticate through another type of Authenticator (as "SimpleAuthenticator), i had to add those in headers of request.

Details :

- Un Objet Json ne fonctionne pas en utilisant "AddQueryParameter", il faut utiliser un string manuel. Il est possible de mettre des variables bien-sûr, mais il faut garder les guillemets juste avant et juste après celles-ci.
- Je n'ai pas pu m'authentifier d'une autre façon qu'en passant par un Header dans la requête (est non dans le client).

If anyone 'working', knowing, or is part of the team charged to write GLPI API REST Documentation is passing by, could he make it changed to be clearer for the "Special Cases" part of it ?
I did not fiund it helpfull to find the best way to Upload a file.
There is in fact a typo mistake : there is no space after "_filename:".
In addition, i believe that what's after the first "-F" parameter (";type=application/json") should be part of a Header, but as i don't have a full aknowledge of all the coding languages, i may be wrong there.

Si quelqu'un passe par là, et connait, ou fait partie de l'équipe qui s'occupe de rédiger la Documentation API, pourrait il faire remonter le fait qu'elle n'aide vraiment pas du tout à comprendre facilement le principe de base.
Et d'ailleurs il y a une "faute de frappe" après "_filename" => il n'y a pas d'espace.
Le "type=application/json" est confus, et sans doute, pas à sa place, il devrait faire partie d'un paramètre "-H", mais là, c'est peut être une spécificité pour d'autre langage, et là, je suis pas assez calé.

$ curl -X POST \
-H 'Content-Type: multipart/form-data' \
-H "Session-Token: 83af7e620c83a50a18d3eac2f6ed05a3ca0bea62" \
-H "App-Token: f7g3csp8mgatg5ebc5elnazakw20i9fyev1qopya7" \
-F 'uploadManifest={"input": {"name": "Uploaded document", "_filename" : ["file.txt"]}};type=application/json' \
-F 'filename[0]=@file.txt' \
'http://path/to/glpi/apirest.php/Document/'

< 201 OK
< Location: http://path/to/glpi/api/Document/1
< {"id": 1, "message": "Document move succeeded.", "upload_result": {...}}

Last edited by BoSaGa (2018-12-02 09:50:38)

Offline

#4 2020-02-05 00:13:21

mathieu.pierluigi
Member
Registered: 2017-04-18
Posts: 3

Re: [SOLVED] Uploading files to GLPI server using C# with RestSharp

Salut Bosaga,

Même galère pour ma part, je tente de convertir ma requête cURL en requête Invoke-RestMethod.
J'ai effectué le test avec un fichier texte vide. L'upload marche en cURL, mais une fois convertis en Invoke-RestMethod, on me retourne une erreur concernant la taille du fichier.

Requête cURL

curl -X POST 
-H 'Content-Type: multipart/form-data'
-H 'Session-Token: $sessiontoken' 
-H 'App-Token:$apptoken' 
-F 'uploadManifest={"input": {"name": "Uploaded document", "_filename" : ["file.txt"]}};type=application/json' 
-F 'filename[0]=@file.txt' 'http://GLPI_SERVER/glpi/apirest.php/Document'

Réponse:

{"id":1,"message":"Élément ajouté : Uploaded document","upload_result":{"filename":[{"name":"5e3197f938b6e0.75084050file.txt","size":3,"type":"text/plain","url":"http://GLPI_SERVER/glpi/files/5e3197f938b6e0.75084050file.txt","deleteUrl":"http://GLPI_SERVER/glpi/apirest.php?filenam=5e3197f938b6e0.75084050file.txt","deleteType":"DELETE","prefix":"5e3197f938b6e0.75084050","display":"file.txt","filesize":"3 o","id":"docfilename1452714730"}]}}


Requête avec Invoke-RestMethod
Génération du token

$uri = 'http://GLPI_SERVER/glpi/apirest.php/initSession'
$contenttype = 'application/json'
$apptoken = 'letoken'
$authorization = 'Basic Z2xwaTpLV3l2KjlBbTI4'

$headers = @{    
    'App-Token' = $apptoken
    'Authorization' = $authorization
    'Content-Type' = $contenttype
}
$sessiontoken=(Invoke-RestMethod -Method Get -Headers $headers -Uri $uri).session_token
$sessiontoken

Upload du document

$contenttype = 'multipart/form-data'
$manifest = @{}
$body = @{}

$headers = @{
    'Content-Type' = $contenttype
    'Session-Token' = $sessiontoken
    'App-Token' = $apptoken
}

$manifest = @{
    uploadManifest =@{
        input = @{
            name = "Uploaded document"
            _filename = '[file.txt]'    
        }
    }
    'filename[0]' = "@C:\file.txt"
}

$body = $manifest | ConvertTo-Json -Compress    
$body


Invoke-RestMethod -Debug -Verbose -Method Post -Headers $headers -Body $body -Uri 'http://GLPI_SERVER/glpi/apirest.php/Document'

Réponse:

Invoke-RestMethod : ["ERROR_UPLOAD_FILE_TOO_BIG_POST_MAX_SIZE","The file seems too big"]
Au caractère C:\FUSIONINVENTORY.ps1:42 : 1
+ Invoke-RestMethod -Debug -Verbose -Method Post -Headers $headers -Body $body -Ur ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation : (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Quoi que je fasse l'erreur est toujours la même, mais je pèche pour trouver où se situe le problème: le body? Le chemin?

Si vous avez un indice, merci d'avance! smile

Offline

#5 2021-04-10 21:23:05

Dead-Red
Member
From: France - Aisne - 02
Registered: 2021-04-10
Posts: 20

Re: [SOLVED] Uploading files to GLPI server using C# with RestSharp

Bonsoir Bonsoir smile

Je dois avoué que je ne trouve pas malgré que je cherche et test depuis plusieurs jours.

Même en me basant sur le code utilisé dans le super plugin : PSGLPI j'obtiens soit la même erreur : ["ERROR_UPLOAD_FILE_TOO_BIG_POST_MAX_SIZE","The file seems too big"]

Mais je pense que c'est à cause du content-type = "multipart/form-data" qui n'est peut être pas supporté.

Car dans la doc de l'API, il est fait mention qu'il est nécessaire d'utiliser : content-type = 'multipart/data'

Sauf que si on l'utilise on fini par avoir : Invoke-RestMethod : ["ERROR_BAD_ARRAY","Le paramètre input doit être un tableau d'objets; ...

En écumant toutes les pages, une personne a indiqué il était nécessaire que le input soit avec [] mais la encore impossible de trouver la bonne syntaxe.

Tout comme dans le plugin PSGLPI la fonction pour uploader est bien présente, mais le plus crucial est manquant dans l'exemple. Il n'y à pas la syntaxe de la variable $Details.

Offline

#6 2023-06-23 11:54:25

jcatrysse
Member
From: Kortrijk, Belgium
Registered: 2023-06-13
Posts: 6

Re: [SOLVED] Uploading files to GLPI server using C# with RestSharp

Impossible de faire passer cela par GuzzleClient, donc voici ma solution alternative :

$uploadManifest = json_encode([
    'input' => [
        'name' => $aFile['description'],
        '_filename' => [$aFile['name']]
    ]
]);

$postData = [
    'uploadManifest' => $uploadManifest,
    'filename[0]' => new \CURLFile($aFile['tmpname'], '', $aFile['name'])
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $glpi_url . '/Document');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Session-Token: ' . $glpi_session_token,
    'App-Token: ' . $glpi_app_token
]);

$response = curl_exec($ch);
curl_close($ch);

// Handle the response
if ($response === false) {
    echo 'Error: ' . curl_error($ch);
} else {
    echo 'Response: ' . $response;
}

Offline

Board footer

Powered by FluxBB