WebSocket closing down on sending Base64 encode Strings - javascript

I'm trying to send a base64 encoded string (converted from a image) via websocket and this is working fine for me with a javascript client.
But if I use a java client (#clientEndPoint) instead, onMessage function is triggered once and the websocket connection immediately closes down. No errors.
Again, I tried sending plain strings from the server and the java client functions properly. But just not with base64 encoded strings.
I'm using Tomcat 7.0.69 and below are the code snippets:
Server End Point:
if (imageToBeSend != null) {
encodedImage = new sun.misc.BASE64Encoder().encode(imageToBeSend);
session.getBasicRemote().sendText(encodedImage);
}
Java client:
#ClientEndpoint
public class SomeClass {
CountDownLatch latch = new CountDownLatch(1);
private Session session;
String msg;
#OnOpen
public void open(Session session) {
this.session = session;
//some stuff
}
#OnClose
public void close(Session session) {
System.out.println("Closing the connection");
}
#OnError
public void onError(Throwable error) {
System.out.println("!!!ERROR!!!!!" + error);
error.printStackTrace();
}
#OnMessage
public void handleMessage(String message, Session session) throws IOException {
System.out.println("got the json string "+message.length());
// more stuff
}
Here the handle message is invoked one time and the corresponding sysout is printed and then immediately onClose is invoked. onError is never invoked.

Related

How do I parse an image sent from Retrofit API from Android (multipart/form) in Python's Flask

I am sending my image as a part of Form Data through Retrofit API. There are no issues loading the image. I am trying to get this image in a Python Flask server.
My python code is not responding the expected way. I have tested my Python code with a JavaScript frontend application and the python server responds as expected. I believe the issue is parsing the multipart/form file which I receive from Android.
There are no network issues, I am able to log the requests. The detectFace() function is not responding as expected for the same image sent through both clients, VueJs and Android.
Any ideas will be appreciated.
Here is the android code for uploading:
private void sendImageToServer() {
File imageFile = loadImageFromStorage(tempImagePath);
RequestBody reqBody = RequestBody.create(MediaType.parse("image/jpeg"), imageFile);
MultipartBody.Part partImage = MultipartBody.Part.createFormData("file", "testImage", reqBody);
API api = RetrofitClient.getInstance().getAPI();
Call<TestResult> upload = api.uploadImage(partImage);
upload.enqueue(new Callback<TestResult>() {
#Override
public void onResponse(Call<TestResult> call, Response<TestResult> response) {
if(response.isSuccessful()) {
TestResult res = response.body();
String jsonRes = new Gson().toJson(response.body());
String result = res.getResult();
Log.v("REST22", result);
}
}
#Override
public void onFailure(Call<TestResult> call, Throwable t) {
Log.v("REST22", t.toString());
Toast.makeText(MainActivity.this, t.toString(), Toast.LENGTH_SHORT).show();
}
});
}
Here is Python code:
#app.route('/detectFaces/', methods=['POST'])
def detectFaces():
img = request.files.get('file')
print('LOG', request.files)
groupName = 'random-group-03'
result = face.detectFaces(img, groupName)
print('RESULT', result)
return {'result' : result[0]}
VueJs - alternate working frontend (REST client):
sendImage(img) {
console.log(img)
var form = new FormData();
form.append('file', img, 'testImage')
axios.post(this.baseUrl + 'detectFaces/?groupName=random-group-03', form)
.then(res => {console.log(res.data); this.log = 'Detected face ids: \n ' + res.data.result});
}

HTTP Post from Postman working but not through browser

I am using JaxRS jersey for server and I have deployed it on aws. Http post request to server is working with postman but not with Http post apache client.
Following is my Java for Rest service
#Path("/data")
public class MyResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
public List<trackerdetails> getIt() {
SessionFactory sessionfactory = new Configuration().configure().buildSessionFactory();
Session session = sessionfactory.openSession();
session.beginTransaction();
trackerdetails user = new trackerdetails();
List<trackerdetails> sendlist = (List<trackerdetails>) session.createQuery("from trackerdetails").list();
session.getTransaction().commit();
session.close();
return sendlist;
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public trackerdetails putit(trackerdetails track) {
track.setDate(new Date());
SessionFactory sessionfactory = new Configuration().configure().buildSessionFactory();
Session session = sessionfactory.openSession();
session.beginTransaction();
session.save(track);
session.getTransaction().commit();
session.close();
return track;
}
Following is my trackerdetails class
#Entity
#XmlRootElement
public class trackerdetails {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private int autoid;
private String latitude;
private String longitude;
private String devicename;
private Date date;
public trackerdetails(){
}
public int getAutoid() {
return autoid;
}
public void setAutoid(int autoid) {
this.autoid = autoid;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getDevicename() {
return devicename;
}
public void setDevicename(String devicename) {
this.devicename = devicename;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
Following is my Client side http post request
HttpPost httpPost = new HttpPost("myurl");
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("devicename", "vip"));
nvps.add(new BasicNameValuePair("date", "hjksvn"));
nvps.add(new BasicNameValuePair("latitude", "hello"));
nvps.add(new BasicNameValuePair("longitude","hi"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
httpPost.setHeader("Cache-Control", "no-cache");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("Host", "trackertest.herokuapp.com");
CloseableHttpResponse response2 = httpclient.execute(httpPost);
try {
System.out.println(response2.getStatusLine());
System.out.println(response2.toString());
HttpEntity entity2 = response2.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
BufferedReader rd = new BufferedReader(
new InputStreamReader(response2.getEntity().getContent()));
StringBuffer result1 = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result1.append(line);
System.out.println(line);
System.out.println("");
}
System.out.println(result1);
EntityUtils.consume(entity2);
} finally {
response2.close();
}
Following is my error status is 400
Bad Requestdescription The request sent by the client was syntactically incorrect.
Your REST API expects request in JSON format but the way you are constructing request body using NameValuePair will not result in JSON format.
You should make a valid JSON request body either by using some libraries which can convert object into JSON like Jackson or you can manually construct JSON request body and then call your API.
Below is one way of manually constructing JSON request body -
HttpPost httpPost = new HttpPost("myurl");
StringBuilder jsonBody = new StringBuilder();
jsonBody.append("{");
jsonBody.append("\"devicename\" : ").append("\"vip\"").append(",");
// Pass a valid date because on server side, you are using Date object for accepting it
jsonBody.append("\"date\" : ").append("\"2017-09-23\"").append(",");
jsonBody.append("\"latitude\" : ").append("\"vip\"").append(",");
jsonBody.append("\"longitude\" : ").append("\"vip\"");
jsonBody.append("}");
StringRequestEntity requestEntity = new StringRequestEntity(jsonBody.toString(),"application/json","UTF-8");
httpPost.setRequestEntity(requestEntity);
httpPost.setHeader("Cache-Control", "no-cache");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("Host", "trackertest.herokuapp.com");
// Rest code should remain same

Efficient way to upload an image to PHP from Android

I am uploading an image to PHP from Android by converting it to the byte array. After that I simply submit it using POST method.
On server side I do the reverse of what I am doing at client (Android app) side.
I was wondering if there is any other good/efficient/smart way to do this.
Note: I only have to use only PHP/JS/HTML and obviously Java at client side.
One of the most efficient ways is doing it using Volley, so make sure to include it in your gradle:
compile 'com.android.volley:volley:1.0.0'
I personally use Universal Image Loader which is included automatically when you include Volley. Since you haven't put any code that you tried, i'll give you some examples. In your activity that you're trying to upload the image, create a button. Add this code when that button is clicked:
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
i.setType("image/*");
startActivityForResult(i, Constants.VALUE_BROWSE_IMAGE_REQUEST);
This will open the gallery in your phone to browse for an image. Declare a variable at the top of your activity:
private Bitmap mBitmap;
After you choose the image you want to upload from your gallery, write this code:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Constants.VALUE_BROWSE_IMAGE_REQUEST &&
resultCode == RESULT_OK &&
data != null) {
try {
// Get the photo URI data
Uri filePath = data.getData();
// Get the Bitmap from Gallery
mBitmap = decodeBitmap(filePath, this);
} catch (IOException e) {
Toast.makeText(this, "Could not open picture.", Toast.LENGTH_SHORT).show();
}
}
}
Now that you have the bitmap of the chosen image, you need to convert that bitmap into base64 string so that Volley can be able to upload it:
// Before uploading the selected image to the server, we need to convert the Bitmap to String.
// This method will convert Bitmap to base64 String.
private String getStringImage(Bitmap bmp) {
ByteArrayOutputStream b = new ByteArrayOutputStream();
// This part handles the image compression. Keep the image quality
// at 70-90 so you don't cause lag when loading it on android
// (0-low quality but fast load, 100-best (original) quality but slow load)
bmp.compress(Bitmap.CompressFormat.JPEG, 80, b);
byte[] imageBytes = b.toByteArray();
String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
return encodedImage;
}
Finally you can start uploading the image:
private void uploadImage() {
StringRequest stringRequest = new StringRequest(
Request.Method.POST,
"URL_TO_YOUR_WEB_API",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "Failed to upload image.", Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
// Converting Bitmap to String
String image = getStringImage(mBitmap);
// Create parameters
Map<String, String> params = new Hashtable<>();
// Add parameters
params.put("action", "YOUR_BACKEND_KEY1");
params.put("...", image);
// Returning parameters
return params;
}
};
// Creating a Request Queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
// Adding request to the queue
requestQueue.add(stringRequest);
}
Make sure to replace the parameter strings with however you have created your backend in php.
Example URL:
http://yoursite.com/api.php?action=uploadimage&imagebase=adwtgiuewohnjsoiu&caption=somecaptiontext
Then the parameters in android would be:
params.put("action", "uploadimage");
params.put("imagebase", image);
params.put("caption", "somecaptiontext");

Downloading a File Via Angular $.http POST

I am trying to download a zipped file that my server generates in my UI. I am at a loss as to how to get the file to download though. We have it setup so that we can download with window.open where we pass the url and it opens a blank page. We need to do a POST where it has a body now. I havent seen a way to send that along with a window.open. Does anyone have any pointers on how i can get access to the returned file?
Here is my current code...
#RequestMapping(method = RequestMethod.POST, value = "/archives/download", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Integer> getArchive(HttpServletResponse response, #RequestBody List<GeneratedReport> reportList) {
System.out.println(reportList.get(0).getFileLocation());
List<String> filesToDownload = new ArrayList<>();
reportList.stream().forEach(e -> filesToDownload.add(e.getFileLocation()));
filesToDownloadAndZip(response, filesToDownload, "zipped_file.zip");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=zipped_file.zip");
return new ResponseEntity<Integer>(200, HttpStatus.OK);
}
private void filesToDownloadAndZip(HttpServletResponse response, List<String> filesToDownload, String archiveFileName) {
try {
ByteArrayOutputStream baos = FileIO.CreateArchive(filesToDownload);
if (baos != null && baos.size() > 0) {
// Set the content type and attachment header.
response.addHeader("Content-disposition", "attachment;filename=" + archiveFileName);
response.setContentType("application/zip");
response.setContentLength(baos.size());
baos.writeTo(response.getOutputStream());
response.flushBuffer();
} else {
LOG.debug("File was null or size 0, try again");
}
} catch(Exception ex)
{
LOG.debug(ex.getMessage());
}
}
The js i have is.....
$http.post('api/archives/download', $scope.downloadItems)
.success(function(data, status, headers, config) {
//I dont know what to do here..... :(
})

Uploading PDF from jsPDF with AJAX using binary data

I am attempting to pass a PDF I have generated on frontend javascript using jsPDF to a Spring Framework MVC backend. Below is the front end code I have written:
var filename = "thefile";
var constructURL = '/daas-rest-services/dashboard/pdfPrintUpload/' + filename;
var url = restService.getUrl(constructURL);
var fileBytes = btoa(pdf.output());
$http.post(url, fileBytes).success(function(data) {
console.log(data);
})
.error(function(e, a) {
console.log(e);
console.log(a);
});
The pdf variable has been generated properly and can confirm is opens correctly when calling pdf.save("filename"). Below is the Java code which has been written on the Spring MVC backend for this call:
#RequestMapping(method = RequestMethod.POST, value = "/pdfPrintUpload/{documentName}")
public #ResponseBody String postPrintDocument(#PathVariable String documentName, #RequestParam byte[] fileBytes) {
String methodName = "postPrintDocument";
if(logger.isLoggable(Level.FINER)){
logger.entering(CLASS_NAME, methodName);
}
String check;
if(fileBytes != null){
check = "not null";
} else {
check = "null ";
}
//Decoding the bytestream
//Save to file location
//return file location
String returnValue = "HI " + documentName + " " + check;
if (logger.isLoggable(Level.FINER)) {
logger.exiting(CLASS_NAME, methodName);
}
return returnValue;
}
Each time I make a request, I am getting 400 Errors telling me:
Error 400: Required byte[] parameter 'fileBytes' is not present
I can confirm in the request payload that a large amount of data is being transmitted, however the backend does not seem to want to accept the parameter.
The purpose of doing this is that I want to be able to get the data from the pdf and then decode it on the backend so I can later publish the pdf to a location on the server. Is there something I am missing in my code for these requests to keep failing, and is there an easier more efficient way to achieve this functionality?
The solution was changing the #RequestParam to #RequestBody. #RequestParam is a parameter which is sent in the path.
#RequestParam vs #PathVariable
Try using ng-file-upload. The link and the examples are available on the link
ng-file-upload
for the sever side code try using this
#RequestMapping(value = "/pdfPrintUpload")
#ResponseBody
public void postPrintDocument(#RequestParam("file") MultipartFile file) {
InputStream is = file.getInputStream();
OutputStream os = new FileOutputStream(/*path to save file*/);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0)
os.write(buffer, 0, length);
is.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Categories