RTC Forums
November 21, 2024, 10:11:10 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Login Register  
Pages: [1]
  Print  
Author Topic: Range check error in Mime_Encode  (Read 4741 times)
WilliamY
RTC License++
*****
Posts: 23


« on: May 26, 2022, 05:27:42 PM »

HI,

We have a TStringStream that hold a PDF Stream in property DataString, whenever we called mime_encode(AStringStream.DataString), we got "Range Check error" in DEBUG mode always.  Could you please take a look? Thanks. using the latest RealThinClient version, and Delphi 10.4

William
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #1 on: May 26, 2022, 07:04:02 PM »

In all Delphi versions with Unicode support (Delphi 2009 and later), always use the Ex version of the function, which expects a RtcByteArray (array of bytes) as a parameter, instead of the old functions, which expect a RtcString (Strings, where only the lower 8 bits of each character should be used) as a parameter, and ONLY exist for backwards compatibility with old Delphi versions, which did NOT have Unicode support.

In other words, instead of using the "Mime_Encode" function with a String as a parameter, use the "Mime_EncodeEx" function and provide an array of bytes as a parameter.

Using a String in Delphi to hold binary data (like a PDF or image file, for example) is generally a bad idea, because Delphi likes to automatically perform conversions between different string types, expecting that the data stored inside the String is Unicode Text and NOT some arbitrary binary sequence (which should NEVER be modified). This is why, especially in Delphi versions with Unicode support, when working with binary data, always use Bytes and Arrays of Bytes, never Strings.
Logged
WilliamY
RTC License++
*****
Posts: 23


« Reply #2 on: May 26, 2022, 08:10:45 PM »

Thanks much for the answer. These codes were old, we just converted our project to Delphi 10.4, so had no enough time to convert them all. so in order to use Ex version of the function, which expects RtcByteArray, how do we do this if we want to send PDF Stream in json to our web server, currently we did this:

js.S['pdfdata'] := mime_encode(PDFStream.DataString);

where js type of ISuperObject,  and PDFStream is type of TStringStream

Thanks
William
Logged
D.Tkalcec (RTC)
Administrator
*****
Posts: 1881


« Reply #3 on: May 26, 2022, 09:37:48 PM »

First of all, you should NOT use a TStringStream when working with binary data in Delphi versions that have native Unicode support, because that can already result in your binary data to get corrupted, due to implicit String type conversions that can be injected by the Delphi compiler. To avoid these unwanted conversions, you need to work with data types that store your binary data as raw bytes and NOT as Unicode characters.

If you are familiar with the TMemoryStream class, you could use it instead of TStringStream for your PDFStream object to store your PDF document in memory without having to worry about data corruption, then you could copy that data into an array of bytes when you want to pass it on to the Mine_EncodeEx function for encoding, or ... if you want a simpler alternative ... you could use the "TRtcByteArrayStream" class from the "rtcSystem.pas" unit, which implements all the necessary methods of a TStream class, but uses an array of bytes internally for data storage, and provides you with a simple read-only "GetBytes" property to access that data directly, as an array of bytes.

In either case, once you have that data in an array of bytes and have passed it on to the Mime_EncodeEx function, you will get another array of bytes back, which should contain that same data in a Base-64 encoding. If you wish to convert that Base-64 encoded binary data into a Delphi String, you can use the RtcBytesToString function from the "rtcSystem.pas" unit.

Long story, short ... if you change your code to make your "PDFStream" into a "TRtcByteArrayStream" instead of a "TStringStream", you should be able to do this ...

js.S['pdfdata'] := RtcBytesToString(Mime_EncodeEx(PDFStream.GetBytes));

... without having to worry about data corruption happening while reading or writing your stream, and ... unless something else is going on here ... without seeing the "Range check Error" popping up while running your code with the Debugger in Delphi.
Logged
WilliamY
RTC License++
*****
Posts: 23


« Reply #4 on: May 27, 2022, 12:50:02 AM »

Great. Thanks for the help, much appreciated!
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.024 seconds with 16 queries.