I have an Android application that calls an .NET WebService that sends back a base64 binary encoded bytes (it's a PDF file).
My goal is to save these bytes as a PDF file on the device's sdcard.
Here is (a small part) the response I get from the WebService :
<base64Binary xmlns="https://www.abcd.com">JVBERi0xLjMKJdP0zOEKM....</base64Binary>
On my application side, I call this WebService using a POST (for authentification purpose) request. I then get the result and parse it with XmlPullParser. The node value (the bytes) is stored in a StringBuilder (is it a good choice?) and I save the file like this :
try
{
FileOutputStream fos = new FileOutputStream(path + "/" + filename);
fos.write(nodeValue.toString().getBytes());
fos.close();
}
catch(FileNotFoundException ex)
{
System.out.println("FileNotFoundException : " + ex);
}
catch(IOException ioe)
{
System.out.println("IOException : " + ioe);
response = false;
}
When I extract the created PDF file with DDMS, and try to open it with Acrobat Reader, I'm getting an error that the file isn't in the right format.
Any idea?
======= ANSWER =======
To solve my problem, I used the kSoap2 library to get the result from the WebService as a SOAP response. Here is how it did the trick.
private static final String SOAP_ACTION = "https://www.foobar.com/getFile";
private static final String METHOD_NAME = "getFile";
private static final String NAMESPACE = "https://www.foobar.com";
private static final String URL = "http://www.foobar.com/ws.asmx";
try
{
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("username", "foo");
request.addProperty("password", "bar");
request.addProperty("file", "foo.pdf");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
envelope.dotNet = true;
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.call(SOAP_ACTION, envelope);
// Get the result
SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
byte[] result = Base64.decode(resultsRequestSOAP.getProperty("getFileResult").toString());
// Save the file
try
{
FileOutputStream fos = new FileOutputStream("/mnt/sdcard/documents/foo.pdf");
fos.write(result);
fos.close();
}
catch(FileNotFoundException ex)
{
System.out.println("FileNotFoundException : " + ex);
}
catch(IOException ioe)
{
System.out.println("IOException : " + ioe);
}
}
catch (Exception e)
{
e.printStackTrace();
}
The line :
byte[] result = Base64.decode(resultsRequestSOAP.getProperty("result").toString());
decodes the result from the String. And the, the byte[] array is saved in a file with :
fos.write(result);
Voilà! Here are the complete code for folks who have the same problem. This is the WebService signature I call :
POST /wsInspection.asmx HTTP/1.1
Host: www.foobar.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "https://www.foobar.com/getFile"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getFile xmlns="https://www.foobar.com">
<username>string</username>
<password>string</password>
<file>string</file>
</getFile>
</soap:Body>
Response :
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getFileResponse xmlns="https://www.foobar.com">
<getFileResult>base64Binary</getFileResult>
</getFileResponse>
</soap:Body>
</soap:Envelope>
Hope it helps! Enjoy.
I think the string you are building and saving is still in base64, which is why it won't open.
You also don't want to use a StringBuilder for the whole content in this case, because a large PDF will use up all the memory for your process.
As you get characters for the element content from the pull parser, do the base64 conversion on the fly and write the converted bytes to the output file.