I want to send image from one device to another so i have created that thing through node.js. i have converted the image into base64 and then into string and then send it to node.js server and decoded that string into another device and everythig works perfect. I have used socket.io. Now the problem arises as i have received the string as json response from node.js the full response is not getting half of response is being trimmed somewhere. So basically i am not getting full JSONRESPONSE. Here is my node.js code.
onLine[data.to].emit('newPrivateMessage1',{from:name, img:data.img.toString('base64'), type:'Private Msg1'})
And here is my first device from where i am sending image.
JSONObject json1 = new JSONObject();
String filepath = Environment.getExternalStorageDirectory().toString()+"/1.png";
File file = new File(filepath);
String itemname = getIntent().getStringExtra("itemname");
try {
#SuppressWarnings("resource")
FileInputStream imageInFile = new FileInputStream(file);
byte imageData[] = new byte[(int) file.length()];
Log.e("TAG", "IMAGEFATABYTE:::" + imageData);
imageInFile.read(imageData);
String imageDataString = android.util.Base64.encodeToString(imageData, 0);
json1.put("img", imageDataString);
json1.put("to", itemname);
Log.e("TAG", "MESSAGE:::" + json1);
socket.emit("privateMessage1", json1);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Here is my second device to get response from json
String josn = getIntent().getStringExtra("pvtjson");
Log.e("TAG5", "IMAGEJSON" + josn);
try {
JSONObject jobj = new JSONObject(josn);
jobj.get("img");
byte[] decodedString = Base64.decode(jobj.get("img").toString(), Base64.DEFAULT);
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
iv.setImageBitmap(decodedByte);
} catch (JSONException e) {
e.printStackTrace();
}
Related
I am currently working on a project in which I want to send an image as ByteArray to a mosquitto broker with java to the topic images.
The subscriber of these Topic is a JavaScript application, which should convert the ByteArray,made in Java, back to an Image.
The reception of the image is working well, but the image cannot be shown correctly.
What I got so far:
Java Code to Publish an Image
public void doDemo(){
try {
client = new MqttClient("tcp://192.168.56.1", "Camera1", new MemoryPersistence());
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
client.connect(connOpts);
MqttMessage message = new MqttMessage();
File imgPath = new File(Reciver.class.getResource("Card_1007330_bg_low_quality_000.png").getPath());
BufferedImage bufferedImage = ImageIO.read(imgPath);
// get DataBufferBytes from Raster
WritableRaster raster = bufferedImage .getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
message.setPayload(data.getData());
client.publish("spengergasse/building-b/2.14/images", message);
} catch (MqttPersistenceException e) {
e.printStackTrace();
} catch (MqttSecurityException e) {
e.printStackTrace();
} catch (MqttException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
}
JavaScript to show the image
function onMessageArrived(r_message){
console.log(r_message);
document.getElementById("ItemPreview").src = "data:image/png;base64," + convert(r_message.payloadBytes);
}
function convert(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
After Reciving the Image I am gettin this:
Maybe someone could help me out.
Thanks a lot :D
Give this a try:
function convert(buffer) {
var decoder = new TextDecoder('utf8');
return btoa(decoder.decode(buffer));
}
I think the best approach here is to use blobs. Instead of converting the array to base64 which is terribly slow an error prone if not done correctly, you create a blob from the input array and assign it to the .src property like this:
var blob = new Blob([r_message.payloadBytes], {type: 'image/png'});
document.getElementById("ItemPreview").src = URL.createObjectURL(blob);
I am using Spring Boot as backend server and I have a JavaScript frontend.
For sending data between front- and backend I'm using the Axios library, which usually works pretty fine.
The Problem:
The image looks like this in the (Chrome) browser console:
It's a very very long alphanumeric string and that's what I send to the server with the following code:
static uploadFiles(files) {
const data = new FormData();
Object.keys(files).forEach(key => {
data.append("files", new Blob([files[key]], { type: 'image/jpeg' }));
});
const url = API_URL + "uploadFiles";
return axios.post(url, data, RestServices.getAuth({
"Content-Type": "multipart/form-data;boundary=gc0p4Jq0M2Yt08jU534c0p"
}));
}
I have no idea what the boundary thing does but it worked to receive a file in the backend tho...
On backend (spring) side I successfully receive an array of MultipartFiles:
#RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
#ResponseBody
public boolean uploadFiles(HttpServletRequest request, #RequestParam("files") MultipartFile[] files) throws IOException {
String filePath = Thread.currentThread().getContextClassLoader().getResource("assets/images/").getFile();
InputStream inputStream;
OutputStream outputStream;
for(MultipartFile file : files) {
File newFile = new File(filePath + file.getOriginalFilename() + ".jpg");
inputStream = file.getInputStream();
if (!newFile.exists() && newFile.createNewFile()) {
outputStream = new FileOutputStream(newFile);
int read;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
}
System.out.println(newFile.getAbsolutePath());
}
return true;
}
I've also tried it file.transferTo(newFile); instead of in- and outputstreams - which didn't work either.
After that I get the following output, which means that the image was saved successfully:
/path/to/blob.jpg
If I check the path where the file was uploaded, there is a file named blob.jpg, but if I open it, the windows photo viewer has the following problem:
I've opened the image before and after upload with notepad++:
Before upload:
I think this is a byte array, but If I open the image after upload I get exactly the output of the browser. This means it didn't get converted to a byte array (correct me if I'm wrong) and I believe that's why it's a corrupt image...
My questions are:
What's the problem?
How can I fix it?
I really tried everything which crossed my mind but I ran out of ideas.
Thanks for your help! :-)
I've read following *related* questions (but they **don't** have an answer):
[Question1][5], [Question2][6], and **many** more...
I've finally found an answer on my own!
I think the problem was that I used the e.target.result (which is used to show the image on the frontend) but insted I had to use the JS File object. The standard HTML 5 file input fields return those File objects (as I've read here).
The only thing I had to do now is to make a FormData object, append the File Object, set the FormData as Body and set the Content-Type header and that's it!
const data = new FormData();
data.append("files", fileObject);
return axios.post(url, data, {
"Content-Type": "multipart/form-data"
});
Those JS File Objects are recognized from Java as Multipart files:
#RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
#ResponseBody
public boolean uploadFiles(HttpServletRequest request, #RequestParam("files") MultipartFile[] files) {
boolean transferSuccessful = true;
for (MultipartFile file : files) {
String extension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.'));
String newFileName = genRandomName() + extension; //set unique name when saving on server
File newFile;
File imageFolder = new File(imageBasePath);
//check if parent folders exist else create it
if(imageFolder .exists() || imageFolder .mkdirs()) {
while ((newFile = new File(imageFolder .getAbsolutePath() + "\\" + newFileName)).exists()) {
newFileName = genRandomName(); //generate new name if file already exists
}
try {
file.transferTo(newFile);
} catch (IOException e) {
e.printStackTrace();
transferSuccessful = false;
}
} else {
LOG.error("Could not create folder at " + imageFolder.getAbsolutePath());
transferSuccessful = false;
}
}
return transferSuccessful;
}
I hope this is helpful :)
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();
}
}
I am passing JSON string to JavaScript code which contains {"imagePath":"a.svg"} Now instead of passing the path I want to send the image as string(some byte code maybe). I will be parsing this string in JavaScript and writing this as image to document.
Convert svg string to base64 and add base64 string to json as property.
Look at example: https://jsfiddle.net/wLftvees/1/
var decodedJson = {
img:
"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBB"+
"ZG9iZSBJbGx1c3RyYXRvciAxNS4xLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9u"+
...
"NSw4LjU5NS0wLjA5NSwxMC42ODIsMS45MDMiLz4NCjwvc3ZnPg0K"
};
document.getElementById('image').src = 'data:image/svg+xml;base64,' + decodedJson.img;
First: Convert your image to String
public static String encodeToString(BufferedImage image, String type) {
String imageString = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ImageIO.write(image, type, bos);
byte[] imageBytes = bos.toByteArray();
BASE64Encoder encoder = new BASE64Encoder();
imageString = encoder.encode(imageBytes);
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
return imageString;
}
Second: Convert String to image
public static BufferedImage decodeToImage(String imageString) {
BufferedImage image = null;
byte[] imageByte;
try {
BASE64Decoder decoder = new BASE64Decoder();
imageByte = decoder.decodeBuffer(imageString);
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
return image;
}
Now you can use 2 function and switch to Javascript to get Image. ^^
I have gzipped json file using below algorithm (from: java gzip can't keep original file's extension name)
private static boolean compress(String inputFileName, String targetFileName){
boolean compressResult=true;
int BUFFER = 1024*4;
byte[] B_ARRAY = new byte[BUFFER];
FileInputStream fins=null;
FileOutputStream fout=null;
GZIPOutputStream zout=null;
try{
File srcFile=new File(inputFileName);
fins=new FileInputStream (srcFile);
File tatgetFile=new File(targetFileName);
fout = new FileOutputStream(tatgetFile);
zout = new GZIPOutputStream(fout);
int number = 0;
while((number = fins.read(B_ARRAY, 0, BUFFER)) != -1){
zout.write(B_ARRAY, 0, number);
}
}catch(Exception e){
e.printStackTrace();
compressResult=false;
}finally{
try {
zout.close();
fout.close();
fins.close();
} catch (IOException e) {
e.printStackTrace();
compressResult=false;
}
}
return compressResult;
}
I am returning the JSON
response.setHeader("Content-Type", "application/json");
response.setHeader("Content-Encoding", "gzip");
response.setHeader("Vary", "Accept-Encoding");
response.setContentType("application/json");
response.setHeader("Content-Disposition","gzip");
response.sendRedirect(filePathurl);
or
request.getRequestDispatcher(filePathurl).forward(request, response);
Trying to access the JSON object using AJAX code as below:
$.ajax({
type : 'GET',
url : url,
headers : {'Accept-Encoding' : 'gzip'},
dataType : 'text',
The output I see is the binary data, not the decompressed JSON string. Any suggestion on how to make this work?
Note that the Browsers I am using (IE, Chrome, FF) supports gzip as all my static contents which are gzipped by Apache are rendered correctly.
By using:
response.sendRedirect(filePathurl);
You are creating another request/response. The headers you have defined are no longer associated with the file that actually gets sent.
Rather than sending a redirect, you need to load up your file and stream it in the same response.
Use Fiddler or another request viewer to see this.