Delphi DLL
Delphi DLL
Xero Get Attachment (Download a Xero Attachment)
Demonstrates how to get the content of an attachment in Xero.Note: This example requires Chilkat v9.5.0.64 or greater.
Chilkat Delphi DLL Downloads
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, BinData, StringBuilder, Rest, Xml;
...
procedure TForm1.Button1Click(Sender: TObject);
var
success: Boolean;
rest: HCkRest;
endPoint: PWideChar;
receiptID: PWideChar;
sbPath: HCkStringBuilder;
numReplaced: Integer;
responseXml: PWideChar;
xml: HCkXml;
numRecords: Integer;
sbSaveFilePath: HCkStringBuilder;
sbAttachmentPath: HCkStringBuilder;
attachmentData: HCkBinData;
i: Integer;
attachmentID: PWideChar;
filename: PWideChar;
statusCode: Integer;
responseBody: PWideChar;
begin
success := False;
// Note: Requires Chilkat v9.5.0.64 or greater.
// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
rest := CkRest_Create();
// Before sending REST API calls, the REST object needs to be
// initialized for OAuth1.
// See Xero 2-Legged OAuth1 Setup for sample code.
// Assuming the REST object's OAuth1 authenticator is setup, and the initial
// connection was made, we may now send REST HTTP requests..
// --------------------------------------------------------------
// First get a list of attachments for a given document (in this case a Receipt).
endPoint := 'Receipts';
receiptID := 'c4f40e59-c390-0001-caff-ce731c707d00';
sbPath := CkStringBuilder_Create();
CkStringBuilder_Append(sbPath,'/api.xro/2.0/{Endpoint}/{Guid}/Attachments/');
numReplaced := CkStringBuilder_Replace(sbPath,'{Endpoint}',endPoint);
numReplaced := CkStringBuilder_Replace(sbPath,'{Guid}',receiptID);
responseXml := CkRest__fullRequestNoBody(rest,'GET',CkStringBuilder__getAsString(sbPath));
if (CkRest_getLastMethodSuccess(rest) <> True) then
begin
Memo1.Lines.Add(CkRest__lastErrorText(rest));
Exit;
end;
// A 200 response is expected for actual success.
if (CkRest_getResponseStatusCode(rest) <> 200) then
begin
Memo1.Lines.Add(responseXml);
Exit;
end;
// Examine the response.
Memo1.Lines.Add(responseXml);
// A sample response looks like this:
// <Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
// <Id>b235646f-34ac-4b15-90ce-d63267f7cd33</Id>
// <Status>OK</Status>
// <ProviderName>ChilkatPrivate</ProviderName>
// <DateTimeUTC>2016-11-11T14:32:17.0908971Z</DateTimeUTC>
// <Attachments>
// <Attachment>
// <AttachmentID>0edcddc8-325f-40c7-b950-8c71f14afc7c</AttachmentID>
// <FileName>penguins.jpg</FileName>
// <Url>http://api.xero.com/api.xro/2.0/Receipts/c4f40e59-c390-0001-caff-ce731c707d00/Attachments/penguins.jpg</Url>
// <MimeType>image/jpg</MimeType>
// <ContentLength>777835</ContentLength>
// </Attachment>
// <Attachment>
// <AttachmentID>0adffdc8-325f-65c7-b950-4391f14af908</AttachmentID>
// <FileName>starfish.jpg</FileName>
// <Url>http://api.xero.com/api.xro/2.0/Receipts/c4f40e59-c390-0001-caff-ce731c707d00/Attachments/starfish.jpg</Url>
// <MimeType>image/jpg</MimeType>
// <ContentLength>24537</ContentLength>
// </Attachment>
// </Attachments>
// </Response>
xml := CkXml_Create();
CkXml_LoadXml(xml,responseXml);
// Iterate over the attachments and download each.
numRecords := CkXml_NumChildrenAt(xml,'Attachments');
Memo1.Lines.Add('Number of Attachments = ' + IntToStr(numRecords));
sbSaveFilePath := CkStringBuilder_Create();
sbAttachmentPath := CkStringBuilder_Create();
attachmentData := CkBinData_Create();
i := 0;
while i < numRecords do
begin
CkXml_putI(xml,i);
attachmentID := CkXml__getChildContent(xml,'Attachments|Attachment[i]|AttachmentID');
filename := CkXml__getChildContent(xml,'Attachments|Attachment[i]|FileName');
Memo1.Lines.Add('AttachmentID: ' + attachmentID);
Memo1.Lines.Add('Filename: ' + filename);
Memo1.Lines.Add('----');
// Download this attachment.
// First build the path for this particular attachment by appending the FileName to the path used to get the list of attachments.
CkStringBuilder_Clear(sbAttachmentPath);
CkStringBuilder_AppendSb(sbAttachmentPath,sbPath);
CkStringBuilder_Append(sbAttachmentPath,filename);
// Send the GET request in one call, and then get the response in the next two.
success := CkRest_SendReqNoBody(rest,'GET',CkStringBuilder__getAsString(sbAttachmentPath));
if (success <> True) then
begin
Memo1.Lines.Add(CkRest__lastErrorText(rest));
Exit;
end;
// Get the response header. If it's not a 200 success status code, then the response body does NOT contain
// the attachment data.
statusCode := CkRest_ReadResponseHeader(rest);
if (statusCode = -1) then
begin
// We didn't get any response..
Memo1.Lines.Add(CkRest__lastErrorText(rest));
Exit;
end;
if (statusCode <> 200) then
begin
Memo1.Lines.Add('Response Status: ' + IntToStr(statusCode));
responseBody := CkRest__readRespBodyString(rest);
if (CkRest_getLastMethodSuccess(rest) <> True) then
begin
Memo1.Lines.Add('Failed to read the response body.');
end
else
begin
Memo1.Lines.Add(responseBody);
end;
Memo1.Lines.Add('Failed.');
Exit;
end;
// OK, the response header indicates the attachment content is forthcoming...
// There are a few ways to get the response body. If it is a very large attachment, it can be streamed directly
// to a file. We'll assume it's not, so we'll get the response into a BinData object, and then save it to a file.
CkBinData_Clear(attachmentData);
success := CkRest_ReadRespBd(rest,attachmentData);
if (success <> True) then
begin
Memo1.Lines.Add(CkRest__lastErrorText(rest));
Exit;
end;
// Save the data to the file.
CkStringBuilder_SetString(sbSaveFilePath,'qa_output/');
CkStringBuilder_Append(sbSaveFilePath,filename);
success := CkBinData_WriteFile(attachmentData,CkStringBuilder__getAsString(sbSaveFilePath));
if (success <> True) then
begin
Memo1.Lines.Add('Failed to save to output file.');
end
else
begin
Memo1.Lines.Add('Saved to ' + CkStringBuilder__getAsString(sbSaveFilePath));
end;
i := i + 1;
end;
CkRest_Dispose(rest);
CkStringBuilder_Dispose(sbPath);
CkXml_Dispose(xml);
CkStringBuilder_Dispose(sbSaveFilePath);
CkStringBuilder_Dispose(sbAttachmentPath);
CkBinData_Dispose(attachmentData);
end;