I'm writing a script with Inno Setup that call my Web API written in C# that returns
File(bytes, "text/plain", "MyFileName.txt");
I read that ResponseText
returns a limited number of chars if is called in synchronous way.
I'm using this code and I receive limited number of chars.
function ActivateLicense(): Boolean;
var
WinHttpReq: Variant;
jsonbody: String;
FStatus: Integer;
Stream: TFileStream;
Buffer: string;
Size: LongInt;
begin
try
WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1');
WinHttpReq.Open('POST', 'http://myweburl', False);
WinHttpReq.SetRequestHeader('Content-Type', 'application/json');
jsonbody := '{"ActivationCode":"' + KeyPage.Values[0] + '"}';
WinHttpReq.Send(jsonbody)
FStatus := WinHttpReq.Status; // 200=OK!
Result := FStatus=200;
if Result then
begin
Stream := TFileStream.Create(WizardDirValue() + '\license\mylicense.txt', fmCreate);
try
Size := WinHttpReq.GetResponseHeader('Content-Length');
Stream.WriteBuffer(WinHttpReq.ResponseText, Size);
finally
Stream.Free;
end;
end
else
begin
Log('HTTP Error: ' + IntToStr(WinHttpReq.Status) + ' ' +
WinHttpReq.StatusText);
MsgBox(WinHttpReq.ResponseText, mbError, MB_OK);
Result := False;
end;
except
MsgBox('Something went wrong trying to connect to our servers.', mbError, MB_OK);
Result := False;
end;
end;
Can I read ResponseText
in async way? Or how can I use the others properties (ResponseBody
, ResponseStream
) of WinHttp.WinHttpRequest.5.1 to get all content?
[ActionName("activate")]
[HttpPost]
public async Task<IActionResult> Activate([FromBody] ActivateLicenseCommand command)
{
try
{
DirectoryInfo d = new DirectoryInfo(_environment.ContentRootPath + @"/licenses/");
FileInfo[] files = d.GetFiles("*.lic"); //Getting the files
if (files.Length != 1)
{
return Problem("There is an error with license's file. Please contact support.");
}
//Download the file
using (FileStream fsSource = new FileStream(files[0].FullName,
FileMode.Open, FileAccess.Read))
{
// Read the source file into a byte array.
byte[] bytes = new byte[fsSource.Length];
int numBytesToRead = (int)fsSource.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
// Read may return anything from 0 to numBytesToRead.
int n = fsSource.Read(bytes, numBytesRead, numBytesToRead);
// Break when the end of the file is reached.
if (n == 0)
break;
numBytesRead += n;
numBytesToRead -= n;
}
numBytesToRead = bytes.Length;
return File(bytes, "text/plain", files[0].Name);
}
}
catch (FileNotFoundException ioEx)
{
return Problem(ioEx.Message);
}
}
The content of the file that I want to send is:
<License>
<Id>0445e5a4-932a-491b-a59d-e017d8eddc1d</Id>
<Type>Standard</Type>
<Expiration>Mon, 21 Nov 2022 13:50:13 GMT</Expiration>
<Quantity>1</Quantity>
<LicenseAttributes>
<Attribute name="generated">2022-10-21 12:50:13Z</Attribute>
<Attribute name="license">2022-11-21 13:50:13Z</Attribute>
<Attribute name="updates">2022-11-21 13:50:13Z</Attribute>
<Attribute name="enableBetaVersions">0</Attribute>
</LicenseAttributes>
<Customer>
<Name>Pippo Pluto</Name>
<Email>pippo@gmail.com</Email>
</Customer>
<Signature>MIGHAkEoiobRz2rFP7Jh8jnIdbGA4mCLbyW9TEpf8VfHkPbXP3lFFi7NlS3K5SKsIPvIk90LdvnCyWTLKduMMwCevuflVQJCAIInvKBiPG4pD0vGZcO/am6vPkl5UDSamxRy49EmeMr0Yb7o6Xqm4oqGS+FuY8hET2oYEZw793o53XLiV1DXaD3W</Signature>
</License>
In Inno Script if I read ResponseText
I don't receive the last character (>
). If I call the Web API from C# method I can read all the content of the file.
For example with :
byte[] fileContent = await response.Content.ReadAsByteArrayAsync();
Imo, your problem is not about reading the response from the server. I think it's the saving the response to the file that is wrong.
Instead of the WriteBuffer
, try my SaveStringToUTF8FileWithoutBOM
function from
Create a UTF8 file without BOM with Inno Setup (Unicode version)
SaveStringToUTF8FileWithoutBOM(
WizardDirValue() + '\license\mylicense.txt', WinHttpReq.ResponseText);
Side note: I believe most of your Activate
method implementation can be reduced to
return File(files[0].FullName, "text/plain", files[0].Name);
No need for all that complicated and inefficient code to load whole file to memory only to return it from the method.