Jump to content
ASavaglio

[Delphi] Indy, upload e download

Recommended Posts

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:

  1. Using username and password I request a token
  2. Using the token that is returned to me, I make another request by sending a file
  3. 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 by ASavaglio

Share this post


Link to post

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 by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×