sending bytes of file

Hi,

We have an xml api that accepts order requests and returns xml responses based on the processing performed.

I would like to add a tag called <Lables> to the xml response that contains the contents (bytes?) of a pdf file generated on our side. I have the bytes[] array and am not sure how to send it in the response. I tried looping theough the byte array and appending the contents to the buffer, but it dumped the contents as integers..not sure if this is readable on the client side.

Please help..the code i have so far is shown below. I want he client side to be able to take the contents between the <Labels></Labels> tag and recreate the pdf file.

Thanks.

try{

File shippingLabels = new File(File.createTempFile("shippingLabel","").getAbsoluteFile() + ".pdf");

BufferedOutputStream sbos = new BufferedOutputStream(new FileOutputStream(shippingLabels));

carrierServiceManager.getShippingLabel(order, sbos);

sbos.flush();

sbos.close();

InputStream is = new FileInputStream(shippingLabels);

long length = shippingLabels.length();

byte[] bytes = new byte[(int)length];

// Read in the bytes

int offset = 0;

int numRead = 0;

while (offset < bytes.length

&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {

offset += numRead;

}

// Ensure all the bytes have been read in

if (offset < bytes.length) {

throw new IOException("Could not completely read file "+ shippingLabels.getName());

}

is.close();

builder.append("<Labels>");

for(int i=0; i<bytes.length; i++)

builder.append(bytes);

builder.append("></Labels>\n");

}

catch(Exception e){

logger.error(e.getMessage());

}

[1850 byte] By [rizmerca] at [2007-10-3 3:29:01]
# 1
Your question contains a bunch of code, so presumably the problem of how to put a PDF file into XML has already been addressed by the people who wrote the specifications for this API.So my first step would be to look at the specifications and see what they say.
DrClapa at 2007-7-14 21:22:44 > top of Java-index,Java Essentials,Java Programming...
# 2

DrClap is right. It would be more proper to send the PDF by some standard and descriptive format, which is the whole point of XML. However, many times it is not convenient to spend the resources to parse and reparse something like that when all you want to do is send it across byte-for-byte. In this case, I reccommend you send it as a hexadecimal string. It's much more efficient than sending it as a sequence of integers. In fact, hexadecimal is close to as small as you can get a binary file without compression into an XML file. Here's some code that returns a hexadecimal String given a java.io.InputStream of the binary data you want to serialize. /**

* The character array representing the hexadecimal characters to use for

* each digit

*/

private static final char [] hexChars = new char [] {'0', '1', '2', '3',

'4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

/**

* Translates a binary input stream into a hexadecimal String

*

* @param is The InputStream to translate

* @return A hexadecimal String that can be used to recreate <code>is</code>'s

* data using the

* {@link #translateBinaryStreamFrom(String, java.io.OutputStream)}

* method

* @throws java.io.IOException If an I/O error occurs while reading from

* <code>is</code>

*/

public static String translateBinaryStream(java.io.InputStream is)

throws java.io.IOException

{

StringBuffer ret = new StringBuffer();

int read = is.read();

while(read >= 0)

{

ret.append(hexChars[read >>> 4]);

ret.append(hexChars[read & 0x0f]);

read = is.read();

}

return ret.toString();

}

And here's the code to translate it back to a java.io.OutputStream/**

* @param hexChar The hexadecimal character in a hex String

* @return The hexadecimal digit <code>hexChar</code> encodes

* @throws java.lang.IllegalArgumentException If <code>hexChar</code> is

* not a valid hexadecimal, i.e. if it is not in one of the ranges

* ('0'...'9'), ('A'...'F'), ('a'...'f')

*/

private static int getHexDigit(char hexChar)

{

if(hexChar >= '0' && hexChar <= '9')

return hexChar - '0';

else if(hexChar >= 'A' && hexChar <= 'F')

return hexChar - 'A' + 10;

else if(hexChar >= 'a' && hexChar <= 'f')

return hexChar - 'a' + 10;

else

throw new IllegalArgumentException("The input string is not in"

+ " hexadecimal format");

}

/**

* Translates a hexadecimal String into binary data, writing it to an

* OutputStream

*

* @param hexString The hexadecimal String to translate

* @param os The OutputStream to write the binary data in

*<code>hexString</code> to

* @throws java.io.IOException If an I/O error occurs while writing to

* <code>os</code>

* @throws java.lang.IllegalArgumentException If any character in

* <code>hexString</code> is not a valid hexadecimal, i.e. if it

* is not in one of the ranges ('0'...'9'), ('A'...'F'), ('a'...'f')

*/

public static void translateBinaryStreamFrom(String hexString,

java.io.OutputStream os) throws java.io.IOException

{

int dig;

int out = 0;

for(int i = 0; i < hexString.length(); i++)

{

dig = getHexDigit(hexString.charAt(i));

if(i % 2 == 0)

{

out = dig << 4;

if(i == hexString.length() - 1)

os.write(out);

}

else

{

out |= dig;

os.write(out);

}

}

}

This code is actually tested. Hope this helps.

Updownquarka at 2007-7-14 21:22:44 > top of Java-index,Java Essentials,Java Programming...
# 3

Thanks for the responses guys...

I am the one writing the specs for the API. So I am trying to figure out what the best way is to send the contents of the pdf file in the xml response.

Updownquark, if I send the pdf contents as a hex string like you mentioned, would the clients be able to read and convert that back to pdf without any platform-related issues? The xml response will go to clients using all kinds of technologies, and I want to make sure they can all read the data and create a pdf document on their side.

rizmerca at 2007-7-14 21:22:44 > top of Java-index,Java Essentials,Java Programming...
# 4

A colleague suggested that I encode the bytes from the file using Base64 and then send the contents in the response. The client would have to receive the data and decode it using base64 as well.

I tried this method and it works (I was able to decode and create the pdf). this is a very simple solution. The only thing I am concerned about is the cross-platform independence.

Can you guys provide some feedbak to the pros and cons of this method? By and large, will it be easy for the clients to decode this data using base64 (irrespective of the platform they are running)?

Thanks,

-Riz.

rizmerca at 2007-7-14 21:22:44 > top of Java-index,Java Essentials,Java Programming...
# 5

> I am the one writing the specs for the API. So I am

> trying to figure out what the best way is to send the

> contents of the pdf file in the xml response.

A common way is to base64-encode the bytes, but encoding them as hex would work too (although it would double the size of the file instead of only increasing it by 1/3).

> Updownquark, if I send the pdf contents as a hex

> string like you mentioned, would the clients be able

> to read and convert that back to pdf without any

> platform-related issues? The xml response will go to

> clients using all kinds of technologies, and I want

> to make sure they can all read the data and create a

> pdf document on their side.

Whatever you choose, you'll have to document your choice so that your partners know how to decode your file. As far as I can see, base-64 and that hex encoding have similar technological complexity.

DrClapa at 2007-7-14 21:22:44 > top of Java-index,Java Essentials,Java Programming...
# 6

PDF files don't have any platform-specific formatting (you can download them from the web onto Mac, Windows, Linux, etc. with no problems). A hex or 64-base string will work fine for you. I personally think that hex, or 16-base, is a little more natural for binary data--it is a little easier to translate back and forth, but 64-base is a good bit smaller for large files, so your performance demands may need that.

Updownquarka at 2007-7-14 21:22:44 > top of Java-index,Java Essentials,Java Programming...