Send image from Android client to AppEngine Cloud Endpoint - java

I am developing an Android applicaiton with AppEngine backend. I am creating the server part with Google Cloud Endpoints in Java. My problem is that I cannot send a Bitmap from the client to the server.
I used the answer from this question but even if the client part does not seem to have any problems at all, the server part does not receive the data at all. I also think this solution might be a bit complicated and that it might work a different, easier way, however this is my first time implementing a server and first time sending a picture to it so I accept any good tips on this. Thanks!
Here is my code:
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
String charset = "UTF-8";
HttpURLConnection connection = (HttpURLConnection) new URL("https://path_to_my_app/_ah/api/registration/v1/uploadImage").openConnection();
connection.setDoOutput(true);
connection.setReadTimeout(60000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
OutputStream output = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!
// Send text file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + somename + "\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF).flush();
BufferedReader reader = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byteArray = stream.toByteArray();
try {
reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(byteArray), charset));
for (String line; (line = reader.readLine()) != null;) {
writer.append(line).append(CRLF);
}
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
writer.flush();
// End of multipart/form-data.
writer.append("--" + boundary + "--").append(CRLF);
}
finally
{
if (writer != null)
{
writer.close();
}
}
The server part:
#ApiMethod(name = "uploadImage", httpMethod = "POST")
public void uploadImage(HttpServletRequest request, HttpServletResponse response) throws IOException
{
ServletFileUpload fileUpload = new ServletFileUpload();
try
{
FileItemIterator iterator = fileUpload.getItemIterator(request);
while(iterator.hasNext()){
FileItemStream itemStream = iterator.next();
String fieldName = itemStream.getFieldName();
log.info("field name:"+fieldName);
InputStream stream = itemStream.openStream();
String result = getStringFromInputStream(stream);
log.info("result: "+result);
stream.close();
}
}
catch (FileUploadException e)
{
e.printStackTrace();
}
}
I am getting 204 no Content type now.

I did it!
I think this is not the best way of doing it but it´s working so I am fine until I get a better solution.
So I take the Bitmap image and convert it to String:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byte[] bitmapByte = outputStream.toByteArray();
String stringEncodedImage = Base64.encodeToString(bitmapByte, Base64.DEFAULT);
Then I create a httpPostRequest and set a JsonObject to it with the image converted to String in it.
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://my_app_path/_ah/api/registration/v1/uploadImage");
JSONObject jsonObject = new JSONObject();
jsonObject.put("image",stringEncodedImage);
StringEntity stringEntity = new StringEntity(jsonObject.toString());
httpPost.addHeader("Content-Type", "application/json");
httpPost.setEntity(stringEntity);
HttpResponse response = httpClient.execute(httpPost);
On the server side, in my Endpoint, I do this:
#ApiMethod(name = "uploadImage", httpMethod = "POST")
public JSONObject uploadImage(JSONObject request) throws IOException
{
String imageInString = (String) request.get("image");
Blob blob = new Blob(imageInString.getBytes());
....save blob and do whatever you want...
}
The same goes the other way. I pack Blob into JsonObject and send it over.

Related

http response multipart binary File in java

I am not able to read multipart file from the http response. The response contains the MIME Boundary and content transfer encoding - binary. we need to read the date from the response and send the request to another http post method. here we are facing two issues.
Not able to read the binary file properly from the http response.
Not able to form the multipart file to send the request.
when I have send that multipart form data in http post method. I am not receiving proper response. beacuse of the multipart binary encoding file. please provide the sample to read the multipart binary file and how to form and send the multipart file.
private void postLocalRequest(URL url, byte[] requestBody, String contentType, String authHeader)
throws IOException, ProtocolException, Exception {
logger.info("local request URL:::" + url);
logger.info("local request content type:::" + contentType);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
if (!authHeader.isEmpty()) {
httpURLConnection.setRequestProperty("Authorization", authHeader);
}
httpURLConnection.addRequestProperty("Accept", "application/json; charset=UTF-8");
httpURLConnection.setRequestProperty("Content-Type", contentType);
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write(requestBody);
outputStream.flush();
logger.info("waiting for local response");
BufferedReader bufferedReader = null;
logger.info("http response code :::" + httpURLConnection.getResponseCode());
deviceResponse = "";
deviceResponseContentType = httpURLConnection.getContentType();
logger.info("device Response Content Type::" + deviceResponseContentType);
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
deviceResponse = bufferedReader.lines().collect(Collectors.joining("\n"));
XWCConnectorSupplementalLogging.logXML(logger, "plr", "Device Request Output", deviceResponse);
} else {
try {
InputStream ip = httpURLConnection.getInputStream();
String info = new BufferedReader(new InputStreamReader(ip)).lines().collect(Collectors.joining("\n"));
deviceResponse = info;
XWCConnectorSupplementalLogging.logXML(logger, "plr", "Device Request Output", info);
} catch (Exception e) {
try {
InputStream es = httpURLConnection.getErrorStream();
String error = new BufferedReader(new InputStreamReader(es)).lines()
.collect(Collectors.joining("\n"));
if(httpURLConnection.getResponseCode() != HttpURLConnection.HTTP_NOT_FOUND) {
deviceResponse = error;
}
XWCConnectorSupplementalLogging.logXML(logger, "plr", "Device Request Error", error);
} catch (Exception e1) {
logger.severe("Unable to read Request error or output");
}
}
}
}

How do i parse content sent from multipart/form-data request to get file in java?

I am sending a HttpURLConnection request to server and trying to send a file. I am able to send file from client side but not sure how can i parse it on the server side.
My code on client side is below.
private void createRequestInCHESS(String sRequestId, String sLastUpdated) {
String boundary = "xyz";
String crlf = "\r\n";
String twoHyphens = "--";
String attachmentName = "file";
String attachmentFileName = "testFile.xlsx";
try {
File file = new File("c:\\MFGREQ-7.xlsx");
URL url = new URL(chess.getMfgRequestURL() + "/createRequest");
HttpURLConnection httpConnecton = (HttpURLConnection) url.openConnection();
httpConnecton.setRequestMethod(REQUEST_METHOD_POST);
httpConnecton.setRequestProperty("Accept", "application/json");
httpConnecton.setRequestProperty("Cache-Control", "no-cache");
httpConnecton.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
httpConnecton.setRequestProperty("id", sRequestId);
httpConnecton.setRequestProperty("lastModified", sLastUpdated);
httpConnecton.setDoOutput(true);
DataOutputStream outStream = new DataOutputStream(httpConnecton.getOutputStream());
outStream.writeBytes(twoHyphens + boundary + crlf);
outStream.writeBytes("Content-Disposition: form-data; name=\"" +
attachmentName + "\";filename=\"" + attachmentFileName + "\"" + crlf);
outStream.writeBytes(crlf);
byte[] bytes = Files.readAllBytes(file.toPath());
outStream.write(bytes);
outStream.flush();
outStream.close();
getResponseString(httpConnecton);
} catch (MalformedURLException me) {
me.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
server side code is given below. What can I use to retrive file sent from request.
#POST
#Path("/createRequest")
public Response createRequest(#Context HttpServletRequest request) {
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(request.getInputStream()))) {
StringBuilder sbPayload = new StringBuilder();
String sLine;
while ((sLine = reader.readLine()) != null) {
sbPayload.append(sLine);
sbPayload.append(System.lineSeparator());
}
String data = sbPayload.toString();
// how do i retrieve file here ?
}
You really don't want to parse that yourself. Use the https://commons.apache.org/proper/commons-fileupload/
Then you can just write.
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8"); // Might be needed, depending on exact setup.
java.util.List<FileItem> items = upload.parseRequest(request);
And then items is the list of uploaded files.
Here is my answer. I have used org.glassfish.jersey.media.multipart.MultiPart on client side.
Client client = ClientBuilder.newBuilder().register(MultiPartFeature.class).build();
WebTarget webTarget = client.target(chess.getMfgRequestURL() + "/createRequest")
.queryParam("id", sRequestId)
.queryParam("lastModified", sLastUpdated);
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file",
file, MediaType.APPLICATION_OCTET_STREAM_TYPE);
#SuppressWarnings("resource")
MultiPart multiPart = new FormDataMultiPart()
.field("json", jsonObj, MediaType.APPLICATION_JSON_TYPE) // json goes here
.bodyPart(fileDataBodyPart); // file goes here
multiPart.bodyPart(fileDataBodyPart);
Response response = webTarget.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(multiPart, multiPart.getMediaType()));
On server side, this is how I have parsed:
#POST
#Path("/createRequest")
#Consumes("multipart/form-data")
public Response createRequest(#Context HttpServletRequest request, #Multipart InputStream uploadedInputStream) throws Exception {
JsonObjectBuilder requestBuilder = null;
try {
String tempDir = "C:\\Users";
String filename = "test.xlsx";
File checkinFile = new File(tempDir, filename);
OutputStream out = new FileOutputStream(checkinFile);
IOUtils.copyStream(uploadedInputStream, out);
}catch (Exception e) {
String errorMessage = e.getMessage();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).build();
}

posting image Invalid mime type

I am trying to post an image from my galery to the server from my android device.
They are using Python in the back office.
That's what the Back office developper say:
- Django cannot read the file posted by the Android app in request.FILES. iOS does this properly.
- It seems the the Multipart POST does not properly set the key:value required to properly read the requests.
I am getting this error:
{"errorMessage":"","message":"Invalid mime
type","errorCode":0,"success":false}
Any idea why?
Here is my code:
public static final String IMAGE_JPEG = "image/jpeg";
private HttpEntity getImageEntity() throws Exception {
File imageFile;
Uri originalUri = Uri.parse(this.mFileName);
String originalPath = originalUri.getPath();
boolean isEncrypted = originalPath.contains(FileNames.CACHE_DIR.getPath());
// check if file encrypted or not
if (isEncrypted && ImageLoader.IMAGE_CODING_ENABLED) {
File originalImageFile = new File(originalPath);
String decodedPath = CipherUtils.decryptFile(SmartPagerApplication.getInstance(), originalImageFile);
imageFile = new File(decodedPath);
} else {
imageFile = new File(originalPath);
}
InputStream fis = imageFile.toURI().toURL().openStream();
int rotation = PhotoFileUtils.getOrientation(this.mFileName);
if (rotation > 0) {
byte[] data;
Bitmap rotateBitmap = PhotoFileUtils.checkOrientation(BitmapFactory.decodeStream(fis), rotation);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
rotateBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
data = stream.toByteArray();
stream.close();
rotateBitmap.recycle();
fis.close();
fis = new ByteArrayInputStream(data);
} else {
// data = IOUtils.toByteArray(fis);
}
return getMultipartEntity(originalUri, fis);
}
private MultipartEntity getMultipartEntity(Uri originalPath, InputStream fis) {
InputStreamBody isb = new InputStreamBody(fis, mMimeType, originalPath.getLastPathSegment());
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,
"----WebKitFormBoundaryzGJGBFWyGteE24tw", Charset.forName("ISO-8859-1"));
multipartEntity.addPart("binaryFile", isb);
return multipartEntity;
}
private String executePost(String url, HttpEntity params) throws ClientProtocolException, IOException {
Log.e("executePost url =" + url);
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "multipart/form-data; boundary="+"----WebKitFormBoundaryzGJGBFWyGteE24tw");
httpPost.addHeader("Cache-Control", "no-cache");
httpPost.setEntity(params);
String response = SmartPagerHTTPClient.getHttpClient().execute(httpPost, new BasicResponseHandler());
return response;
}
I don't have enough reputation to comment, so I have to put this as an answer. In you method getMultipartEntity(), the first line:
InputStreamBody isb = new InputStreamBody(fis, mMimeType, originalPath.getLastPathSegment());
What is the value of mMimeType? Please make sure it's a correct mime type.
This is an OKHttp implementation
first, you need to include it in dependencies:
compile 'com.squareup.okhttp:okhttp:2.4.0'
Actual upload code : Call within an Asynctask
File upload;
upload = new File("<<Your Path to image>>");
Response response;
String finalResponce;
try {
RequestBody body = new MultipartBuilder()
.addFormDataPart("Image", upload.getName(), RequestBody.create(MediaType.parse("image/jpeg"), upload))
.build();
Request request = new Request.Builder()
.url("https://iamin-events.appspot.com/UploadServlet")
.post(body)
.build();
response = new OkHttpClient().newCall(request).execute();
finalResponce = response.body().string();
finalResponce = finalResponce.trim();
mainEventListing.setBackdropUrl(finalResponce);
} catch (Exception e) {
// show error
e.printStackTrace();
}
This is my code for uploading images.The "Content-Type" is like that httpConnection.setRequestProperty("Content-Type", "image/jpeg");
public String doPutUploadImage(File image) throws Exception {
String imageUrl = "http://" + Const.BUCKET_NAME
+ ".oss-cn-hangzhou.aliyuncs.com/" + image.getName();
URL localURL = new URL(imageUrl);
URLConnection connection = localURL.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setDoOutput(true);
httpConnection.setRequestMethod("PUT");
httpConnection.setRequestProperty("Host",
Const.BUCKET_NAME.concat(".oss-cn-hangzhou.aliyuncs.com"));
String GMTDate = SignatureMaker.getGMTDate();
if(!GMTDate.contains("+")){
httpConnection.setRequestProperty("Date", GMTDate);
}else{
GMTDate=GMTDate.substring(0, GMTDate.indexOf("+"));
httpConnection.setRequestProperty("Date", GMTDate);
}
httpConnection.setRequestProperty("Content-Encoding", "UTF-8");
httpConnection.setRequestProperty("Content-Type", "image/jpeg");
httpConnection.setRequestProperty("Content-Length",
String.valueOf(image.length()));
httpConnection.setRequestProperty("Authorization",
"OSS "+ ACCESS_ID+ ":"
+ SignatureMaker.makeSignature(ACCESS_KEY, "PUT",
Const.BUCKET_NAME, image, GMTDate));
sendRequest(httpConnection, image);
return imageUrl;
}
Instead of MultipartEntity, I suggest that you use MultipartEntityBuilder with HttpURLConnection. Then, you can refer to my following code (pay attention to ContentType contentType = ContentType.create("image/jpeg");):
...
byte[] bitmapData = byteArrayOutputStream.toByteArray();
String address = "http://192.168.1.100/api/postfile";
String boundary = "----apiclient----" + System.currentTimeMillis();
String mimeType = "multipart/form-data;boundary=" + boundary;
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(boundary);
// Add binary body
if (bitmapData != null) {
ContentType contentType = ContentType.create("image/jpeg"); //CREATE ContentType for the file part
String fileName = "some_file_name.jpeg";
entityBuilder.addBinaryBody("binaryFile", bitmapData, contentType, fileName);
try {
URL url = new URL(address);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", mimeType);
entityBuilder.build().writeTo(urlConnection.getOutputStream());
JSONObject jsonObject = new JSONObject();
try {
if (urlConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
// process urlConnection.getInputStream();
} else {
// process urlConnection.getErrorStream();
}
jsonObject.put("Message", urlConnection.getResponseMessage());
jsonObject.put("Length", urlConnection.getContentLength());
jsonObject.put("Type", urlConnection.getContentType());
} catch (IOException | JSONException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
...
If you still want to use MultipartEntityBuilder with HttpPost, you can refer to the following:
...
byte[] bytes = byteArrayOutputStream.toByteArray();
ContentType contentType = ContentType.create("image/jpeg");
String fileName = "some_filename.jpg";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// Add binary body
builder.addBinaryBody("binaryFile", bytes, contentType, fileName);
HttpEntity httpEntity = builder.build();
httpPost.setEntity(httpEntity);
...
You can find out that addBinaryBody in MultipartEntityBuilder class has many implementations such as:
public MultipartEntityBuilder addBinaryBody(String name, InputStream stream, ContentType contentType, String filename)
public MultipartEntityBuilder addBinaryBody(String name, File file, ContentType contentType, String filename)
public MultipartEntityBuilder addBinaryBody(String name, byte[] b, ContentType contentType, String filename)
...
Hope this helps!
I think this issue is because you are setting Content-Type yourself in code, I once had same issue in my case I just removed the Content-Type and It worked. If you remove the Content-Type, you mean that library will detect its Content-Type based on its type.
just remove this line
httpPost.setHeader("Content-Type", "multipart/form-data; boundary="+"----WebKitFormBoundaryzGJGBFWyGteE24tw");
Here is what i am doing and works fine for me -
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("photo", new FileBody(new File(imagePath), "image/jpeg"));
httppost.setEntity(entity);
According to this org.apache.http documentation Change your mime-type static declaration
public static final String IMAGE_JPEG = "image/jpeg";
to
public static final String IMAGE_JPEG = "image/png";
In addition to the #BNK answer Instead of MultipartEntity, you can use MultipartEntityBuilder with HttpURLConnection. In that you can upload the image as a binary body and there you can set the type and the name:
multiPartEntityBuilder.addBinaryBody(imageName, byteArray, ContentType.create("image/png"), "image.png");
You are probably running your code on Android 4.0.x which has buggy implementation for multipart/form-data (httpclient). This issue has been reported earlier and has a work around here

How to setEntity on a HttpURLConnection

In my project I must strictly use HttpURLConnection class
I have this following code which I got from the internet
MultipartEntity multiPart = new MultiPartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null Chartset.forName("UTF-8");
File f = new File("/home/abhishek/foo.docx");
FileBody fb = new FileBody(f);
multiPart.addPart("file", fb);
HttpPost post = new HttpPost();
post.setHeader("ENCTYPE", "multipart/form-data");
post.setEntity(multiPart);
Problem is that I cannot use HttpPost ... In my project only HttpURLConnection class works!
So I need to translate the code above into HttpURLConnection.
I cannot find anything similar to setEntity on the HttpUrlConnection.
Edit::
Based on the suggestions below. I have this code
public class RESTFileUpload {
public static void main(String[] args) throws Exception {
Authenticator.setDefault(new Authenticator() {
#Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("domain\\user", "Password".toCharArray());
}
});
String filePath = "/home/abhishek/Documents/HelloWorld.docx";
String fileName = "HelloWorld.docx";
String fileNameShort = "HelloWorld";
String urlStr = "https://sp.company.com/sites/abhi_test/_vti_bin/listdata.svc/SharedDocuments/RootFolder/Files/add(url=#TargetFileName,overwrite='true')&#TargetFileName=" + fileName;
String crlf = "\r\n";
String twoHypens = "--";
String boundary = "*****";
URL url = new URL(urlStr);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestMethod("POST");
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Cache-Control", "no-cache");
con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream request = new DataOutputStream(con.getOutputStream());
request.writeBytes(twoHypens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data;name=\"" + fileNameShort + "\";fileName=\"" + fileName + "\"" + crlf);
request.writeBytes(crlf);
request.write(convertToByteArray(filePath));
request.writeBytes(crlf);
request.writeBytes(twoHypens + boundary + twoHypens + crlf);
request.flush();
request.close();
InputStream responseStream = new BufferedInputStream(con.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder strBuilder = new StringBuilder();
while((line = responseStreamReader.readLine()) != null) {
strBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = strBuilder.toString();
responseStream.close();
con.disconnect();
System.out.println(response);
}
private static byte[] convertToByteArray(String filePath) {
File f = new File(filePath);
byte[] retVal = new byte[(int)f.length()];
try {
FileInputStream fis = new FileInputStream(f);
fis.read(retVal);
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch(IOException ex2) {
ex2.printStackTrace();
}
return retVal;
}
}
But I get the error
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 400 for URL: https://sp.web.gs.com/sites/abhi_test/_vti_bin/listdata.svc/SharedDocuments/
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1626)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at RESTFileUpload.main(RESTFileUpload.java:62)
HttpURLConnection has .getInputStream() and .getOutputStream() methods. If you wish to send body content with an Http request, you call .setDoOutput(true) on your HttpURLConnection object, call .getOutputStream() to get an Output stream and then write the content of your entity to the output stream (either as raw bytes, or using a Writer implementation of some sort), closing it when you are finished writing.
For more details, see the API docs for HttpURLConnection here.
To post files using the HttpURLConnection you have to compose the file wrapper manually. Take a look at this answer, it should be helpful for you.

Error reading xml from doPost HttpServletRequest

I am trying to read the XML file being posted using http doPost method. While parsing using SAXParser it throws an Exception:
Content is not allowed in prolog.
The doPost code is:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
{
ServletInputStream httpIn = request.getInputStream();
byte[] httpInData = new byte[request.getContentLength()];
StringBuffer readBuffer = new StringBuffer();
int retVal = -1;
while ((retVal = httpIn.read(httpInData)) != -1)
{
for (int i=0; i<retVal; i++)
{
readBuffer.append(Character.toString((char)httpInData[i]));
}
}
System.out.println("XML Received" + readBuffer);
try
{
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
ByteArrayInputStream inputStream = new ByteArrayInputStream(
readBuffer.toString().getBytes("UTF-8"));
final XmlParser xmlParser = new XmlParser();
parser.parse(inputStream, xmlParser);
}
catch (Exception e)
{
System.out.println("Exception parsing the xml request" + e);
}
}
This is the JUnit I am testing with:
public static void main(String args[])
{
StringBuffer buffer = new StringBuffer();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
buffer.append("<person>");
buffer.append("<name>abc</name>");
buffer.append("<age>25</age>");
buffer.append("</person>");
try
{
urlParameters = URLEncoder.encode(buffer.toString(), "UTF-8");
}
catch (Exception e1)
{
e1.printStackTrace();
}
String targetURL = "http://localhost:8888/TestService";
URL url;
HttpURLConnection connection = null;
try
{
//Create connection
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml");
connection.setRequestProperty("Content-Length", "" +
Integer.toString(urlParameters.getBytes("UTF-8").length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches (false);
connection.setDoInput(true);
connection.setDoOutput(true);
//Send request
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
}
catch (Exception e)
{
e.printStackTrace();
}
The XML output in the servlet that I am getting is something like this:
XML Received %3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%3Cperson%3E%
So this is throwing an exception in SAXparser:
What am I doing wrong? Am I sending the XML in wrong way or reading it wrong way?
You assume
httpInData[i]
is a char, while it is a byte. Your content being UTF-8, that makes a big difference. Use a Reader instead.
Then, you are URLEncoding your XML, which is useless, as it is a POST data. Don't encode it, simply send the data.
replace
urlParameters = URLEncoder.encode(buffer.toString(), "UTF-8");
by
urlParameters = buffer.toString();
Also, the name urlParameter is poorly chosen, as this is a single post body, doesn't go in the url, and isn't really a parameter.

Categories

Resources