2017-02-20 3 views
2

J'essaie de faire multipart upload to Box.com en utilisant TIdMultipartFormDataStream. Bien que le nom de fichier soit '\ u0424 \ u042B \ u0412 \ u0410 \ u041F.txt \ ", il fonctionne correctement, mais quand il est plus long (' \ u0424 \ u0424 \ u0412 \ u0410 \ u041F \ u0420.txt ') il provoque' HTTP /1.1 400 Mauvaise demande '.Indy 10 + XE8 téléchargement en plusieurs parties avec long nom de fichier

Existe-t-il une limitation pour la longueur FormField.FFieldValue? Si oui, y a-t-il un moyen de le contourner?

procedure TBoxComSaveFilter.UploadTest; 
const 
    URL = 'https://upload.box.com/api/2.0/files/content'; 
var 
    IdHTTP: TIdHTTP; 
    MD: TIdMultipartFormDataStream; 
begin 
    IdHTTP := TIdHTTP.Create(nil); 
    try 
    IdHTTP.HandleRedirects := True; 
    IdHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP); 
    IdHTTP.Request.BasicAuthentication := False; 
    IdHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + FAccessToken; 
    MD := TIdMultipartFormDataStream.Create; 
    try 
     MD.AddFormField('metadata', '{"name": "' + 
     '\u0424\u042B\u0412\u0410\u041F.txt' +  // => OK 
//  '\u0424\u042B\u0412\u0410\u041F\u0420.txt' + // => 400 Bad Request 
     '", "parent": {"id": "0"}}', '', 'application/json'); 

     MD.AddFile('content', 'source.txt', 'application/octet-stream'); 
     IdHTTP.Post(URL, MD); 
    finally 
     MD.Free; 
    end; 
    finally 
    IdHTTP.Free; 
    end; 
end; 

Un journal partiel pour nom de fichier court:

Sent 20.02.2017 21:16:26: ----------022017211625520 
Content-Disposition: form-data; name="metadata" 
Content-Type: application/json 
Content-Transfer-Encoding: quoted-printable 

{"name": "\u0424\u042B\u0412\u0410\u041F.txt", "parent": {"id": "0"}} 
----------022017211625520 

La même partie pour nom de fichier long:

Sent 20.02.2017 21:17:48: ----------022017211748412 
Content-Disposition: form-data; name="metadata" 
Content-Type: application/json 
Content-Transfer-Encoding: quoted-printable 

{"name": "\u0424\u042B\u0412\u0410\u041F\u0420.txt", "parent": {"id": = 
"0"}} 
----------022017211748412 

Comme je peux voir la répartition des données après 70 octets par "= CRLF" .

+0

Il n'y a pas de limite dans 'TIdMultipartFormDataStream' lui-même, mais il y a à la fin de Box:" * Box ne supporte que les noms de fichiers de 255 caractères ou moins. Les noms qui ne seront pas supportés sont ceux qui contiennent des noms ascii,/ou \, avec des espaces de fin, et les noms spéciaux "." Et "..". * " –

+0

Pourquoi encoder JSON les caractères Unicode, Vous ne devriez pas avoir besoin de faire cela: 'MD.AddFormField ('metadata', '{" name ":" ФЫВАПР.txt "," parent ": {" id ":" 0 "}}', 'utf- 8 ',' application/json '); ' –

+0

Merci @RemyLebeau.J'ai essayé" ФЫВАПР.txt "et' utf-8 'et le résultat était' HTTP/1.1 400 Bad Request 'Le journal:' {"name" : "= D0 = A4 = D0 = AB = D0 = 92 = D0 = 90 = D0 = 9F = D0 = A0.txt", "parent": {"id": = CRLF' '" 0 "}}' –

Répondre

7

Le codage de transfert par défaut pour les champs de texte est le format quoted-printable de MIME. Il semblerait que Box n'aime pas ce format.

AddFormField() retourne un TIdFormDataField, qui possède une propriété ContentTransfer vous pouvez le mettre à 8bit ou binary d'envoyer le texte JSON en l'état (après il est charset codé en octets, qui est):

MD.AddFormField('metadata', '{"name": "ФЫВАПР.txt", "parent": {"id": "0"}}', 'utf-8', 'application/json').ContentTransfer := '8bit'; 

vous pouvez également mettre votre JSON dans un TStream, comme TStringStream ou TMemoryStream, puis utilisez la surcharge TStream de AddFormField(), qui fixe le ContentTransfer à binary par défaut: 01

JsonStream := TStringStream.Create('{"name": "ФЫВАПР.txt", "parent": {"id": "0"}}', TEncoding.UTF8); 
try 
    MD.AddFormField('metadata', 'application/json', 'utf-8', JsonStream); 
    // send the post... 
finally 
    JsonStream.Free; 
end; 
+0

Vos deux méthodes fonctionnent bien.J'ai essayé TMemoryStream comme [multipart télécharger sur OneDrive] (http: //stackoverflow.com/questions/42157101/indy-10-multipart-upload-to-onedrive-error): il fonctionne aussi Merci @RemyLebeau. –