Сохранение байтов из.NET WebService из Android
У меня есть приложение Android, которое вызывает.NET WebService, который отправляет обратно двоичные байты с кодировкой base64 (это файл PDF).
Моя цель - сохранить эти байты в виде файла PDF на SD-карте устройства.
Вот (небольшая часть) ответ, который я получаю от WebService:
<base64Binary xmlns="https://www.abcd.com">JVBERi0xLjMKJdP0zOEKM....</base64Binary>
Что касается приложения, я вызываю этот WebService с помощью запроса POST (для целей аутентификации). Затем я получаю результат и анализирую его с помощью XmlPullParser. Значение узла (байты) хранится в StringBuilder (это хороший выбор?), И я сохраняю файл следующим образом:
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;
}
Когда я извлекаю созданный файл PDF с помощью DDMS и пытаюсь открыть его с помощью Acrobat Reader, я получаю сообщение об ошибке, что файл имеет неправильный формат.
Любая идея?
======= ОТВЕТ =======
Чтобы решить мою проблему, я использовал библиотеку kSoap2 для получения результата от WebService в качестве ответа SOAP. Вот как это получилось.
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();
}
Линия:
byte[] result = Base64.decode(resultsRequestSOAP.getProperty("result").toString());
декодирует результат из строки. И, массив byte[] сохраняется в файле с:
fos.write(result);
Вуаля! Вот полный код для людей, которые имеют ту же проблему. Это подпись WebService, которую я называю:
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>
Отклик:
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>
Надеюсь, поможет! Наслаждаться.
2 ответа
Я думаю, что строка, которую вы строите и сохраняете, все еще находится в base64, поэтому она не открывается.
Вы также не хотите использовать StringBuilder для всего содержимого в этом случае, потому что большой PDF будет использовать всю память для вашего процесса.
Когда вы получаете символы для содержимого элемента из парсера pull, выполняйте преобразование base64 на лету и записывайте преобразованные байты в выходной файл.
Ошибка должна быть в пути к файлу. Попробуй это:
FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + File.Separator + filename);