Home > Software design >  Send a PUT request with a file and custom headers
Send a PUT request with a file and custom headers

Time:11-05

I am stuck at a problem. I need to upload a file (a CSV file) to a server by using Delphi. The server have certain requirements that must be followed :

  • The request must be an HTTP PUT request.
  • Must countains the Client ID in the URL request, like this : example.com/upload/{Client ID} ({Client ID} would be replaced).
  • Must contain the future file name that will be received also in the URL after the client ID, like this : example.com/upload/{Client ID}/{Future File Name} ({Future File Name} would be replaced), which can be different from your local file name.
  • The API Key must be in the request header (header name: x-api-key). Example : lXViWTzFic9sM8qe9Ew7JME8xTdBAOMJHdIjK7XkjQ00OWr.

I could do this in CURL, like this example : (Client ID : d32krpq, and Future file name : 20181023_update.csv)

curl -v -X PUT https://example.com/upload/d32krpq/20181023_update.csv --upload-file 20181023_update.csv --header "x-api-key: lXViWTzFic9sM8qe9Ew7JME8xTdBAOMJHdIjK7XkjQ00OWr"

How to achieve this in Delphi components ? (In either TNetHttpClient or TRESTClient).

CodePudding user response:

In Delphi, sending multiple fields (files, custom headers, ...) in your "Put" request is possible in both HTTP client frameworks :

In "TNetHTTPClient" through the method "Put", you can use the overloaded function function function function with either the local file path's string or the "TMultipartFormData" object (if you want to include many files and other fields). And in the function's optional parameter of "TNetHeaders" object, you specify your custom header parameters. "TNetHeaders" is a dynamic array of the "TNameValuePair" record. So, you have to create a dynamic array of "TNameValuePair", then you create an instance of the "TNameValuePair" record with your API key and add it to the dynamic array. With the exception that in "TNetHTTPClient" you have to specify the URL segments parameter directly in your URL's request. And finally, you call the "Put" method with your file path's string (or "TMultipartFormData" if you used it) and "TNetHeaders" objects, like this example :

procedure TForm1.PutFile; 
var 
LHTTP: TNetHTTPClient; 
LHeaders: array of TNameValuePair;

begin
SetLength(LHeaders, 1);
LHeaders[0] := TNameValuePair.Create('x-api-key', 'lXViWTzFic9sM8qe9Ew7JME8xTdBAOMJHdIjK7XkjQ00OWr');

LHTTP := TNetHTTPClient.Create(nil);
  try
  LHTTP.Put('https://example.com/upload/d32krpq/20181023_update.csv', 'C:/MyFile.csv', nil, LHeaders);
  finally
  LHTTP.Free;
  end;
end; 

For the REST Client library, you can simply use the TRESTRequest "AddFile" function to add a file, and you can use the "AddParameter" to add any custom fields as a body, an URL segment or a header parameter. Another advantage in TRESTClient is that you can use a base URL or a resource where you define URL segments, like "example.com/upload/{Client ID}/{Future File Name}". Drop the components "TRESTClient", "TRESTRequest" and "TRESTResponse" on the form, set the "TRESTClient" BaseURL to your upload server, and write your code. Like in this example:

procedure TForm1.PutFile;
begin
  try
    try
    RESTRequest1.Method := TRESTRequestMethod.rmPUT;
    RESTRequest1.AddFile('File1', 'C:\MyFile.csv', TRESTContentType.ctTEXT_CSV);

    // Adding the parameters to be included in the URL
    RESTRequest1.AddField('Client ID', 'd32krpq', pkURLSEGMENT);
    RESTRequest1.AddField('Future File Name', '20181023_update.csv', pkURLSEGMENT);

    // Adding a header parameter
    RESTRequest1.AddField('x-api-key', 'lXViWTzFic9sM8qe9Ew7JME8xTdBAOMJHdIjK7XkjQ00OWr', pkHTTPHeader);

    RESTRequest1.Execute; 
    except
    ShowMessage('Uploading failed'); 
    end;
  finally 
  ShowMessage(RESTRequest1.Response.Content); // here you can see your server's response
  end; 
end;
  • Related