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]

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.
> 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.