Introduction

We’ve been developing extensions for Microsoft Dynamics Business Central for some time and we stumbled upon a quite interesting problem – sending an HTTP Post request with an attached file.

The Body of the Request

An example request containing a file would have the following body.

POST https://www.someurl.com/ HTTP/1.1
Content-Type: multipart/form-data; boundary=boundary
...

--boundary
Content-Disposition: form-data; name="key1"

value1
--boundary
Content-Disposition: form-data; name="key2"

value2
--boundary
Content-Disposition: form-data; name="file1"; filename="Test.mp3"
Content-Type: application/octet-stream

<File contents go here>
--boundary

When you send such a request with AL, you need to construct the request body yourself.

Binary Data

Everything goes smooth until you get to the point of converting a stream of bytes to text. The problem we encountered was that just using InStream.ReadText produced corrupt file data.

FileInStream.ReadText(FileDataAsText);

The Solution

After spending a lot of time figuring this out, we managed to leverage the use of multiple streams to properly serialize the binary file data to the request body. The trick here is that writing the request content from a stream will retain the encoding. That is why everything is written to a stream and then the stream is used to create the request content.

procedure UploadFile(UploadStream: InStream)
var
    TempBlob: Record TempBlob temporary;
    PayloadOutStream: OutStream;
    PayloadInStream: InStream;
    CR: Char;
    LF: Char;
    NewLine: Text;
    Content: HttpContent;
    ContentHeaders: HttpHeaders;
    Client: HttpClient;
    Request: HttpRequestMessage;
    Response: HttpResponseMessage;
begin
    CR := 13;
    LF := 10;
    NewLine += '' + CR + LF;

    Content.GetHeaders(ContentHeaders);
    ContentHeaders.Clear();
    ContentHeaders.Add('Content-Type', 'multipart/form-data;boundary=boundary');

    // IMPORTANT: The following stream operations are necessary because
    // if we convert the uploaded file stream to text, we will lose encoding
    // and the data will be corrupt.

    // Create a new temporary stream for writing and write all of the
    // request text in it.
    TempBlob.Blob.CreateOutStream(PayloadOutStream);

    PayloadOutStream.WriteText('--boundary' + NewLine);
    // key1 value1
    PayloadOutStream.WriteText('Content-Disposition: form-data; name="key1"' + NewLine);
    PayloadOutStream.WriteText(NewLine);
    PayloadOutStream.WriteText('value1' + NewLine);
    PayloadOutStream.WriteText('--boundary' + NewLine);
    // key2 value2
    PayloadOutStream.WriteText('Content-Disposition: form-data; name="key2"' + NewLine);
    PayloadOutStream.WriteText(NewLine);
    PayloadOutStream.WriteText('value2' + NewLine);
    PayloadOutStream.WriteText('--boundary' + NewLine);
    // file1
    PayloadOutStream.WriteText('Content-Disposition: form-data; name="file1"; fileName="Test.mp3"' + NewLine);
    PayloadOutStream.WriteText('Content-Type: application/octet-stream' + NewLine);
    PayloadOutStream.WriteText(NewLine);
    // Copy all bytes from the uploaded file to the stream.
    CopyStream(PayloadOutStream, UploadStream);
    PayloadOutStream.WriteText(NewLine);
    PayloadOutStream.WriteText('--boundary');

    // Copy all bytes from the write stream to a read stream.
    TempBlob.Blob.CreateInStream(PayloadInStream);

    // Write all bytes from the request body stream.
    Content.WriteFrom(PayloadInStream);

    Request.Content := Content;
    Request.SetRequestUri('https://www.someurl.com/');
    Request.Method := 'POST';

    Client.Send(Request, Response);

    if not Response.IsSuccessStatusCode() then
        Error('Failed to upload the file.');
end;

22 Comments

Victor Sijtsma · May 18, 2020 at 20:51

You Rock!!

This is indeed the right way, it even works with AL language.

Tnx!!

Rasmus · August 26, 2020 at 11:27

Thanks a million!

But whats the deal with the broken data?
Why cant we directly set the content to the instream from our blob on the record?
Why does it have to got to through a temp blob, what is the deal? haah

    Nikolay Arhangelov · August 26, 2020 at 11:49

    The problem was in the combining of the text content of the body with the file bytes. This lead to a loss of encoding. Everything had to be put into a stream and then passed to the request.

Developer · September 23, 2020 at 14:43

I am trying to use this same code and send JSON and PDF in multipart/form-data to Django

Django is receiving the request but its having blank JSON

below is code
BoundaryText2 := DELCHR(FORMAT(CURRENTDATETIME), ‘=’, DELCHR(FORMAT(CURRENTDATETIME, 1000), ‘=’, ‘1234567890’));
BoundaryText := ‘—-‘ + BoundaryText2;//DELCHR(FORMAT(CURRENTDATETIME), ‘=’, DELCHR(FORMAT(CURRENTDATETIME, 1000), ‘=’, ‘1234567890’));
Multipart := ‘multipart/form-data; boundary=’ + BoundaryText;
////Send
SMBTranMgt.GetAPICredMuti(APICred, Multipart);
//Attach PDF

TempBlob.Blob.CreateOutStream(PayloadOutStream);

PayloadOutStream.WriteText(BoundaryText + NewLine);
// key1 value1
PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”invoice”‘ + NewLine);
PayloadOutStream.WriteText(NewLine);
PayloadOutStream.WriteText(‘value1’ + NewLine);
PayloadOutStream.WriteText(BoundaryText + NewLine);
// key2 value2
PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”document_header”‘ + NewLine);
PayloadOutStream.WriteText(NewLine);
PayloadOutStream.WriteText(‘value2’ + NewLine);
PayloadOutStream.WriteText(BoundaryText + NewLine);
// file1
PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”invoice”; fileName=”‘ + STRSUBSTNO(‘SalesInvoice_%1.Pdf’, SalesInvoiceHeader2.”No.”) + NewLine);
PayloadOutStream.WriteText(‘Content-Type: application/pdf’ + NewLine);
PayloadOutStream.WriteText(NewLine);
// Copy all bytes from the uploaded file to the stream.
CopyStream(PayloadOutStream, DocStream2);
PayloadOutStream.WriteText(NewLine);
PayloadOutStream.WriteText(BoundaryText);

// file2
PayloadOutStream.WriteText(StrSubstNo(‘Content-Disposition: form-data; filename=”%1″‘, ‘document_header’) + NewLine);
PayloadOutStream.WriteText(‘Content-Type: application/json’ + NewLine);
PayloadOutStream.WriteText(NewLine);
// Copy all bytes from the uploaded file to the stream.
CopyStream(PayloadOutStream, UploadStream);
PayloadOutStream.WriteText(NewLine);
PayloadOutStream.WriteText(BoundaryText);
// Copy all bytes from the write stream to a read stream.
TempBlob.Blob.CreateInStream(PayloadInStream);

RequestContent.WriteFrom(PayloadInStream);

contentHeaders := APICred.DefaultRequestHeaders;
RequestContent.GetHeaders(contentHeaders);
contentHeaders.Clear();
contentHeaders.Add(‘Content-Type’, Multipart);

///Call POST Action with JSON Object
APICred.Post(URL, RequestContent, UploadResponse);
IF Not UploadResponse.IsSuccessStatusCode then
Error(‘Error in sending Http request’);

Help is appreciated,

    Nikolay Arhangelov · September 23, 2020 at 16:29

    Did you inspect the request that gets generated and sent? It might be something with the boundaries.

Developer · September 23, 2020 at 18:26

Thanks for your input Boundaries was having issue, I corrected it.

    Ravi · October 8, 2020 at 15:27

    Hi, i am getting issue while using it :

    Misordered multipart fields; files should follow ‘map’.

    Quick Help is appreciated 🙂

Ravi · October 8, 2020 at 15:30

While using it, i am getting one error message :

Misordered multipart fields; files should follow ‘map’

Quick Help is appreciated. 🙂

    Nikolay Arhangelov · October 8, 2020 at 15:34

    Can you send a sample of the request that is being generated?

      Ravi · October 8, 2020 at 18:13

      Hi Nikolay,
      This is the sample code.
      Content in ***** are a bit confidential.
      So shared as :

      procedure UploadFile(UploadStream: InStream)
      var
      TempBlob: Codeunit “Temp Blob”;
      PayloadOutStream: OutStream;
      PayloadInStream: InStream;
      CR: Char;
      LF: Char;
      NewLine: Text;
      Content: HttpContent;
      ContentHeaders: HttpHeaders;
      Client: HttpClient;
      Request: HttpRequestMessage;
      Response: HttpResponseMessage;
      OutputResultJson: Text;
      begin
      CR := 13;
      LF := 10;
      NewLine += ” + CR + LF;
      Content.GetHeaders(ContentHeaders);
      ContentHeaders.Clear();
      ContentHeaders.Add(‘x-apim’, ‘*************’);
      ContentHeaders.Add(‘x-tenant’, ‘****************’);
      ContentHeaders.Add(‘Content-Type’, ‘multipart/form-data;boundary=boundary’);

      TempBlob.CreateOutStream(PayloadOutStream);
      PayloadOutStream.WriteText(‘–boundary’ + NewLine);
      // key1 value1
      PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”key1″‘ + NewLine);
      PayloadOutStream.WriteText(NewLine);
      PayloadOutStream.WriteText(‘value1’ + NewLine);
      PayloadOutStream.WriteText(‘–boundary’ + NewLine);
      // key2 value2
      PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”key2″‘ + NewLine);
      PayloadOutStream.WriteText(NewLine);
      PayloadOutStream.WriteText(‘value2’ + NewLine);
      PayloadOutStream.WriteText(‘–boundary’ + NewLine);
      // file1
      PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”file1″; fileName=”Test.pdf”‘ + NewLine);
      PayloadOutStream.WriteText(‘Content-Type: application/octet-stream’ + NewLine);
      PayloadOutStream.WriteText(NewLine);
      // Copy all bytes from the uploaded file to the stream.
      CopyStream(PayloadOutStream, UploadStream);
      PayloadOutStream.WriteText(NewLine);
      PayloadOutStream.WriteText(‘–boundary’);
      // Copy all bytes from the write stream to a read stream.
      TempBlob.CreateInStream(PayloadInStream);
      // Write all bytes from the request body stream.
      Content.WriteFrom(PayloadInStream);
      Request.Content := Content;
      Request.SetRequestUri(‘https://******************/’);
      Request.Method := ‘POST’;
      Client.Send(Request, Response);
      if not Response.IsSuccessStatusCode() then begin
      Message(Response.ReasonPhrase + ‘\Error Code : ‘ + format(Response.HttpStatusCode));
      Response.Content().ReadAs(OutputResultJson);
      Message(OutputResultJson);
      end;

      end;

        Nikolay Arhangelov · October 8, 2020 at 18:27

        Hello Ravi, can you send the raw http request that the code generates? It will be easier to troubleshoot the problem by looking at the request.

          Ravi · October 8, 2020 at 18:37

          Since i am using it on AL so i sent it this way.
          Is there any way get exact http request in AL ??

        Ravi · October 9, 2020 at 11:00

        Also, i found one thing.
        At end i checked the text in PayloadInstream.
        its only ‘–boundry’ not the entire query that i want to send.

Stijn · January 28, 2021 at 19:22

Hello,

Any idea if this trick works when one is receiving binary information from a webservice (AZ Devops API).
Now I end up with corrupt files everytime.
I’m about to try anyway 🙂

    Mark Bisson · September 1, 2022 at 15:45

    Hey, did you ever manage to handle the binary data in the response?

Dev · February 12, 2022 at 22:52

Hi;

I am facing problem in sending two pdf files on server, I got two files but second is always zero length though its working text files. Not sure how to check request in this case. Thank you for helping

Francesco Lanza · November 12, 2022 at 12:29

I have an issue. I am tryng to upload a file, but in http header request i also have an x-authorization element.

the correct curl request, if i test the call via swagger, is

curl -X POST –header ‘Content-Type: multipart/form-data’ –header ‘Accept: application/json’ –header ‘X-Authorization: H4sIAAAAAAAEAIWRzW6cMBSFXwV5OzL+wcYGAVGSQdFMq6kyZTWbymAzQZnaCENL+mpZ9JH6CoX8SK1UqQv76urK3z0+59fzz+xq/noJvpnBd87mgIQYBMY2Tnf2nINpbKEEV0X22TTT0I1Pt86OZh4r92hs0JN0p3PwpTUtI1QL2ES1gEy1DCYtj6FuOZdNKzRPFNxSRiNexiTB4laWkpYcb6+3N4JyGZVJAoJFiPVpT3LwMI59ipB2jQ+d8p2Hrjc2dMMZffceUYwZwgS9jtYOE7gM1vOmE05jd1nr8qFw9vqN/h809PPLvUJM4+xqixoXY9aVnFBQZDtt7Ni1nRmKabDpNHU6JUrWtRIG6riOIKsjCZXmAiqR1IzEIsKaZeiPl1nl3vWo+gIKiimFhEBCK0JTLlMeh4QIynCywSTFOEOVW0Lozjaonnqz5AT+AiSzMXeDODzcn8q7e+mOe7b/ePzxgcl+c2TR5qBOn/Yn7dvDLs/QyimW8o9Mi99E2kwxEwIAAA==’ -F request=%7B%20%09%22identificativoDocumento%22%3A%20%22%22%2C%20%09%22campiMetadatiSistema%22%3A%20%5B%20%09%09%7B%20%09%09%09%22tipo%22%3A%20%22HASH_SHA256%22%2C%20%09%09%09%22valore%22%3A%20%22cbe7a8455d857e660b276ff15ce8dde7488e9d417f5073476039780809a5fb64%22%20%09%09%7D%20%09%5D%2C%20%09%20%09%20%09%22profiliDocumento%22%3A%20%5B%20%09%09%7B%20%09%09%09%22campiMetadati%22%3A%20%5B%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22MITTENTE-NOME%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22NomePersona%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22MITTENTE-COGNOME%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22CognomePersona%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22MITTENTE-CODFISC%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22CodiceFiscalePersona%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22DESTINATARIO-NOME%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22NomePersona%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22DESTINATARIO-COGNOME%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22CognomePersona%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22DESTINATARIO-CODFISC%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22CodiceFiscalePersona%22%20%09%09%09%09%7D%2C%09%09%09%09%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22DATA_FATTURA%22%2C%20%09%09%09%09%09%22valore%22%3A%20%222021-01-01%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22NUMERO_FATTURA%22%2C%20%09%09%09%09%09%22valore%22%3A%20%221%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22OGGETTO%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22Questo%20un%20oggetto%22%20%09%09%09%09%7D%2C%20%09%09%09%09%7B%20%09%09%09%09%09%22nome%22%3A%20%22SEZIONALE_IVA%22%2C%20%09%09%09%09%09%22valore%22%3A%20%22PIPPO2%22%20%09%09%09%09%7D%09%09%20%09%09%09%09%20%09%09%09%5D%20%09%09%7D%20%09%09%20%09%5D%2C%20%20%7D ‘https://ixapidemo.arxivar.it/Conservation/api/v2/versamento/versamenti/236E6ACF-5E33-4453-9D87-532088A638BF/documenti’

in the “request” form-data there is a json, wich is not a problem. I am trying to adapt the procedure in this way:

============== al code =================
CR := 13;
LF := 10;
NewLine += ” + CR + LF;
FileName2 := ‘tuamadre.txt’;

Content.GetHeaders(ContentHeaders);
ContentHeaders.Clear();
ContentHeaders := Client.DefaultRequestHeaders();

ContentHeaders.add(‘Accept’, ‘application/json’);
ContentHeaders.add(‘X-Authorization’, Delchr(p_AccessToken, ‘=’, ‘”‘));
ContentHeaders.Add(‘Content-Type’, ‘multipart/form-data; boundary=”123456789″‘);

// IMPORTANT: The following stream operations are necessary because
// if we convert the uploaded file stream to text, we will lose encoding
// and the data will be corrupt.

// Create a new temporary stream for writing and write all of the
// request text in it.
TempBlob.CreateOutStream(PayloadOutStream);

PayloadOutStream.WriteText(‘–123456789–‘ + NewLine);
// key1 value1
PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”request”‘ + NewLine);
PayloadOutStream.WriteText(NewLine);
PayloadOutStream.WriteText(p_PayloadMetadata + NewLine);
//PayloadOutStream.WriteText(‘value’ + NewLine);
PayloadOutStream.WriteText(‘–123456789–‘ + NewLine);
// key2 value2
/* PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”key2″‘ + NewLine);
PayloadOutStream.WriteText(NewLine);
PayloadOutStream.WriteText(‘value2’ + NewLine);
PayloadOutStream.WriteText(‘–boundary’ + NewLine); */
// file1
//ContentHeaders.Add(‘Content-Type’, ‘multipart/form-data;boundary=boundary’);
PayloadOutStream.WriteText(‘Content-Disposition: form-data; name=”file”; fileName=”‘ + Filename + ‘”‘ + NewLine);
PayloadOutStream.WriteText(‘Content-Type: application/octet-stream’ + NewLine);
PayloadOutStream.WriteText(NewLine);
// Copy all bytes from the uploaded file to the stream.
CopyStream(PayloadOutStream, PayLoadStream);
PayloadOutStream.WriteText(NewLine);
PayloadOutStream.WriteText(‘–123456789–‘);

// Copy all bytes from the write stream to a read stream.
TempBlob.CreateInStream(PayloadInStream);
DownloadFromStream(PayloadInStream, ‘Export’, ”, ‘All files(*.*)|*.*’, FileName2);
// Write all bytes from the request body stream.
Content.WriteFrom(PayloadInStream);

Request.Content := Content;
Request.SetRequestUri(p_RequestUrl);
Request.Method := ‘POST’;

Client.Send(Request, Response);

Response.Content().ReadAs(ResponseText);

IXCELog.Init();
IXCELog.Daterequest := CREATEDATETIME(WorkDate(), 0T);
IXCELog.Request := copystr(p_RequestUrl, 1, 2048);
IXCELog.Response := CopyStr(ResponseText, 1, 2048);
IXCELog.Insert();

if not Response.IsSuccessStatusCode() then
Error(ErrorResponse, ResponseText);

exit(ResponseText);

============== al code =================

I got an error in this line:

ContentHeaders.Add(‘Content-Type’, ‘multipart/form-data; boundary=”123456789″‘);

end the error is quite nasty:

System.InvalidOperationException: Nome dell’intestazione usato in modo non valido. Verificare che le intestazioni della richiesta vengano usate con l’oggetto HttpRequestMessage, le intestazioni della risposta con HttpResponseMessage e le intestazioni del contenuto con HttpContent.
in System.Net.Http.Headers.HttpHeaders.CheckHeaderName(String name)
in System.Net.Http.Headers.HttpHeaders.Add(String name, String value)
in Microsoft.Dynamics.Nav.Runtime.TrappableHttpOperationExecutor.c__DisplayClass0_0.b__0()
in Microsoft.Dynamics.Nav.Runtime.TrappableOperationExecutor.Execute(DataError errorLevel, Func`1 operation, Action`2 processNativeException)

I am doing something wrong but I cannot see it.
Please help me 🙂
Cheers
Francesco

Francisco Gil · December 15, 2022 at 17:57

I take my time to thank you. This helped me a lot.

Kindest regards,

Francisco · December 15, 2022 at 18:13

However, this only works with pdf files. Any idea about office files?

Ilker Kilincarslan · March 6, 2023 at 18:28

I am trying to send a ZPL content via text file. I am trying to implement SendFileToPrinter api from Zebra. I successfully attached related file and send the request in postman. It takes 2 parameters at Header (apikey, tenant) and 2 parameters at Body (form-data) zpl_file and sn

its sending the file content instead of the file itself.

TempBlob2.CreateInStream(ZPLInStr);
UploadIntoStream(‘Upload ZPL’, ”, ”, varFile, ZPLInStr);

CR := 13;
LF := 10;
NewLine += ” + CR + LF;

Content.GetHeaders(ContentHeaders);
ContentHeaders.Clear();
ContentHeaders.Add(‘apikey’, ‘**************’);
ContentHeaders.Add(‘tenant’, ‘**************’);
ContentHeaders.Add(‘sn’, ‘**************’);
ContentHeaders.Add(‘Content-Type’, ‘multipart/form-data;boundary=boundary’);

TempBlob.CreateOutStream(payloadOuts);

payloadOuts.WriteText(‘–boundary’);
payloadOuts.WriteText(NewLine);
payloadOuts.WriteText(‘Content-Disposition: form-data; name=”key1″‘ + NewLine);
payloadOuts.WriteText(NewLine);
payloadOuts.WriteText(‘value1’ + NewLine);
payloadOuts.WriteText(‘–boundary’ + NewLine);

payloadOuts.WriteText(‘–boundary’ + NewLine);
payloadOuts.WriteText(‘Content-Disposition: form-data; name=”key2″‘ + NewLine);
payloadOuts.WriteText(NewLine);
payloadOuts.WriteText(‘value2’ + NewLine);
payloadOuts.WriteText(‘–boundary’ + NewLine);

// payloadOuts.WriteText(StrSubstNo(‘Content-Disposition: form-data; name=”zpl_file”; fileName=”%1″‘, FileName) + NewLine);
payloadOuts.WriteText(StrSubstNo(‘Content-Disposition: form-data; name=”file1″; fileName=”%1″‘, FileName) + NewLine);
payloadOuts.WriteText(‘Content-Type: application/octet-stream’ + NewLine);
payloadOuts.WriteText(NewLine);

CopyStream(payloadOuts, ZPLInStr);
payloadOuts.WriteText(NewLine);
payloadOuts.WriteText(‘–boundary’);

TempBlob.CreateInStream(payloadIns);

Content.WriteFrom(payloadIns);

HttpRequest.Content := Content;
HttpRequest.SetRequestUri(‘https://api.zebra.com/v2/devices/printers/send’);
HttpRequest.Method := ‘POST’;
Client.Send(HttpRequest, HttpResponse);

if (HttpResponse.HttpStatusCode() 200) then begin
Content.ReadAs(ContentTxt);
Message(ContentTxt);
Error(‘Call failed. (status code %1) %2:%3’, HttpResponse.HttpStatusCode(), HttpResponse.ReasonPhrase(), HttpResponse.Content);
end;
// Commit();

Message(‘File has been sent to printer.’);

Here is the output from ContentTxt;

–boundaryContent-Disposition: form-data; name=”key1″

value1
–boundary
–boundary
Content-Disposition: form-data; name=”key2″

value2
–boundary
Content-Disposition: form-data; name=”file1″; fileName=”WO-20221017-001 3×1.txt”
Content-Type: application/text

^XA
^FO400,2^GFA,427,427,7,,:003NF8,003N0C,::::::::::::::::003N08,001M018,0018L038,I0EL06,I038J018,J0EJ06,J03I01C,J01C003,K0600E,K03008,:K0300C,K0E006,J01C0038,J07J0E,I01CJ038,I07L0C,I0EL07,0018L018,003N08,:003N0C,003NFC,:::::::::::::::003NF8,,:^FS
^FO10,05
^FO20,10^GB45,30,2^FS
^FO25,17^A0,25,28^FDSN^FS
^FO68,17^A0,25^FDSN-0121^FS
^FO450,20^A0,25^FD2024-02-07^FS
^FO20,60^A0,30^FDRestore GF Amniotic Fluid 2.0cc^FS
^FO450,80^A0,13^FDLabel # 0301SN Rev.01^FS
^FO20,110^BY3^BCN,70,N,N,N,A^FDSN-0121^FS
^XZ

–boundary

What should i do any ideas ?

Sebastiaan Lubbers · March 7, 2024 at 10:04

Your sample is missing the multipart boundary footer. The last line should be:

–boundary–

Otherwise the receiving end will not know what the end of the message is, and most of the time just give an error.

Alex · July 30, 2024 at 13:05

Thank you

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *