ASavaglio 0 Posted April 27, 2023 (edited) Good morning to all the community. My need is to send a file that should be processed and then download the result of this processing. All this is expected and working in fact the procedure is already used through java code. But I have to do it in Delphi and for this I use the IdHTTP component together with IdSSL. I've been passed the Java code and I've tried translating it into Delphi, the operational sequence should be as follows: Using username and password I request a token Using the token that is returned to me, I make another request by sending a file The response should contain another file that is generated by remote processing Now point 1 (requesting the token) works and also point 2 seems to work, but point 3 doesn't return anything: maybe I'm wrong to send the file? Maybe nothing comes? Surely I'm doing something wrong and I would like to submit the portion of Java code that works and the Delphi code that I wrote. The Login function, which requires the token, I think works, the one that is wrong is the InviaRiceviFile procedure. I will be grateful if you can (and will) give me some suggestions, some ideas, anything to help me overcome this block. Thank you all. Java code: public class testAuthFunction{ private static final String functionUri = <indirizzo del portale che riceve ed invia i file>; private static final String tokenUri = <indirizzo del portale che riceve credenziali e genera il token>; private static final String tokenToAskForAToken = <b64 di username:password>; private static final String bdapFilePath = "F:\\BDAP_C_2020.zip"; //file di input private static final String bdapZipFilePath = "F:\\tmp\\XBRL_BDAP_C_2020.zip"; //file di output public static void main( String[] args ) throws Exception { try{ //prova di chiamata CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost uploadFile = new HttpPost(functionUri); uploadFile.addHeader("Authorization", authExplicit()); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); // Attacco il file al post File f = new File(bdapFilePath); builder.addBinaryBody( "file", new FileInputStream(f), ContentType.APPLICATION_OCTET_STREAM, f.getName() ); HttpEntity multipart = builder.build(); uploadFile.setEntity(multipart); //spedisco la richiesta CloseableHttpResponse response = httpClient.execute(uploadFile); HttpEntity responseEntity = response.getEntity(); File zip = new File(bdapZipFilePath); OutputStream responseOutputStream = new FileOutputStream(zip); responseEntity.writeTo(responseOutputStream); responseOutputStream.close(); //fine prova di chiamata }catch (IOException ieo){ ieo.printStackTrace(); } } static String authExplicit() throws IOException { String token = null; try{ //prova di chiamata CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost askToken = new HttpPost(tokenUri); //aggiungiamo tutti gli header di Ivan askToken.addHeader("Authorization", "Basic " + tokenToAskForAToken); askToken.addHeader("Content-Type", "application/x-www-form-urlencoded"); //askToken.addHeader("Content-Length", "29"); HttpEntity body = new StringEntity("grant_type=client_credentials"); askToken.setEntity(body); //spedisco la richiesta CloseableHttpResponse response = httpClient.execute(askToken); HttpEntity responseEntity = response.getEntity(); //stampo la risposta System.out.println("HEADER"); for (Header mioheader : response.getAllHeaders()) { System.out.println(mioheader.toString()); } System.out.println("CONTENT"); token = IOUtils.toString(responseEntity.getContent(),"UTF-8"); System.out.println(token); //tiro fuori cosi il token, dovrei prendermi il campo access token token = token.substring(17, token.indexOf("\",\"expires_in\"")); System.out.println(token); }catch (IOException ieo){ ieo.printStackTrace(); } return "bearer " + token ; } } Delphi code: function Login: string; const tokenUri = <https del portale che riceve credenziali e genera il token>; tokenToAskForAToken = <token string>; var Params: TStringList; Token: string; begin Result := ''; IdHttp1.Request.CustomHeaders.AddValue('Authorization', 'Basic ' + tokenToAskForAToken); IdHttp1.Request.CustomHeaders.AddValue('Content-Type', 'application/x-www-form-urlencoded'); Params := TStringList.Create; try try Params.Add('grant_type=client_credentials'); Token := IdHTTP1.Post(tokenUri, Params); Memo1.Lines.Add(Token); Result := 'bearer ' + Token except on E:Exception do Memo2.Lines.Add(E.Classname + ': ' + E.Message); end; finally Params.Free; end; end; procedure InviaRiceviFile; const functionUri = <https del portale che riceve ed invia i file>; bdapFilePath = 'c:\temp\BDAP_P_2022.zip'; //file di input bdapZipFilePath = 'c:\temp\XBRL_BDAP_P_2022.txt'; //file di output var Params: TIdMultiPartFormDataStream; Response: TMemoryStream; begin idhttp2.Request.BasicAuthentication := True; IdHttp2.Request.CustomHeaders.Values['Authorization'] := Login; Params := TIdMultiPartFormDataStream.Create; Response := TMemoryStream.Create; try try Params.AddFormField('file', bdapFilePath, 'application/octet-stream'); IdHttp2.Post(functionUri, Params, Response); Response.SaveToFile(bdapZipFilePath); // <- this creates an empty file :( except on E:Exception do Memo2.Lines.Add(E.Classname + ': ' + E.Message); end; finally Params.Free; Response.Free; end; Edited April 27, 2023 by ASavaglio Share this post Link to post
Remy Lebeau 1421 Posted April 27, 2023 (edited) Your InviaRiceviFile() function is using the wrong Add method of TIdMultipartFormDataStream. You should be using either AddFile() or the TStream overload of AddFormField(). You are using the String overload of AddFormField() instead, which is meant for text fields, not binary data fields. So, you are setting the content of the 'file' field to be just the file path itself, rather than the content of the file that is located at the path. On a side note, don't use the TIdHTTP.Request.CustomHeaders property to specify a 'Content-Type' header, use the TIdHTTP.Request.ContentType property instead. Note that the TStrings overload of the TIdHTTP.Post() method already sets the ContentType to 'application/x-www-form-urlencoded' for you. Also, when using the TIdHTTP.Request.CustomHeaders property to send your own 'Authorization' header, the TIdHTTP.Request.BasicAuthentication property should be set to False, not to True. With that said, try this: function Login: string; const tokenUri = <https del portale che riceve credenziali e genera il token>; tokenToAskForAToken = <token string>; var Params: TStringList; Token: string; begin Result := ''; idhttp2.Request.BasicAuthentication := False; IdHttp1.Request.CustomHeaders.AddValue('Authorization', 'Basic ' + tokenToAskForAToken); IdHttp1.Request.ContentType := 'application/x-www-form-urlencoded'; try Params := TStringList.Create; try Params.Add('grant_type=client_credentials'); Token := IdHTTP1.Post(tokenUri, Params); Memo1.Lines.Add(Token); Result := 'bearer ' + Token; finally Params.Free; end; except on E: Exception do Memo2.Lines.Add(E.Classname + ': ' + E.Message); end; end; procedure InviaRiceviFile; const functionUri = <https del portale che riceve ed invia i file>; bdapFilePath = 'c:\temp\BDAP_P_2022.zip'; //file di input bdapZipFilePath = 'c:\temp\XBRL_BDAP_P_2022.txt'; //file di output var Params: TIdMultiPartFormDataStream; Response: TMemoryStream; begin idhttp2.Request.BasicAuthentication := False; IdHttp2.Request.CustomHeaders.Values['Authorization'] := Login; try Params := TIdMultiPartFormDataStream.Create; try Response := TMemoryStream.Create; try Params.AddFile('file', bdapFilePath, 'application/octet-stream'); IdHttp2.Post(functionUri, Params, Response); Response.SaveToFile(bdapZipFilePath); finally Response.Free; end; finally Params.Free; end; except on E: Exception do Memo2.Lines.Add(E.Classname + ': ' + E.Message); end; end; Edited April 27, 2023 by Remy Lebeau Share this post Link to post
ASavaglio 0 Posted April 28, 2023 You are great: it works! Thank you very much! Share this post Link to post