I am Creating a chat app between two users now I can do Simple text chat with different users using node.js and socket.io. Now problem arises here as I have to send image in chat application and after searching for whole long day I am not able to get perfect node.js in which I can send image in chat app. So I want to know is it possible to send image using node.js. Here is my simple node.js file for sending simple text message from one user to another.
socket.on('privateMessage', function(data) {
socket.get('name', function (err, name) {
if(!err) {
// get the user from list by its name to get its socket,
// then emit event privateMessage
// again here we want to make you clear
// that every single client connection has its own
// unique SOcket Object, we need to get this Socket object
// to communicate with every other client. The socket variable
// in this scope is the client who wants to send the private
// message but the socket of the receiver is not know.
// Get it from the saved list when connectMe handlers gets called
// by each user.
onLine[data.to].emit('newPrivateMessage',{from:name, msg:data.msg, type:'Private Msg'})
}
});
});
You can use the Base64 version of your image and send it like this:
onLine[data.to].emit('newPrivateMessage',{from:name, img:data.img.toString('base64'), type:'Private Msg'})
.. and then on the client side receive it and create an image
socket.on("newPrivateMessage", function(data) {
if (data.img) {
var img = new Image();
img.src = 'data:image/jpeg;base64,' + data.img;
// Do whatever you want with your image.
}
});
UPDATE
The following is a snippet taken from the link I've commented below. As you can see it takes the image from the input, reads it and sends to the server. After that you can send the same data from the server to another client.
For the full example, please read the article.
JavaScript (client)
...
$('#imageFile').on('change', function(e) {
var file = e.originalEvent.target.files[0],
reader = new FileReader();
reader.onload = function(evt) {
var jsonObject = {
'imageData': evt.target.result
}
// send a custom socket message to server
socket.emit('user image', jsonObject);
};
reader.readAsDataURL(file);
});
...
HTML
...
Image file: <input type="file" id="imageFile" /><br/>
...
UPDATE 2
Here is one example I have found:
Java (client)
File file = new File("path/to/the/image");
try {
FileInputStream imageInFile = new FileInputStream(file);
byte imageData[] = new byte[(int) file.length()];
imageInFile.read(imageData);
// Converting Image byte array into Base64 String
String imageDataString = Base64.encodeBase64URLSafeString(imageData);
} catch (...) {
...
}
The above snippet shows how to read the file and encode the data into a base64 string. So then you can send it just like a string (I assume).
Here is the complete example: How to convert Image to String and String to Image in Java?
Also I have found encodeToString function of Base64.Encoder (java.util package), which you can use.
The easiest way I can think of is to simply Base64 encode the image and send it through the text pipe. You would need to distinguish text and image messages with header information (Maybe send a JSON object?).
Related
Short version
I have a webapp using Magnolia, I need to upload a comment with posibility of multiple files, I want to use AJAX, before saving the files as assets I want to be able to check the user's permission, I figured I need a custom Java-based REST endpoint, I made it work, but I have issues saving "jcr:data" into an asset.
Long version
I have a webapp, I have registered users (using PUR), I have different roles for users (for simplicity let's say User and Editor) and I have a Post and a Comment content types. Every User can create a Post and add files, every Post holds the creator's UUID, array of Comment UUIDs and array of file UUIDs (from Assets app), every Post has a comment section and every Comment can have files attached (zero or multiple) to it. Every Editor can post a comment to every Post, but Users can only post comments to their own Posts.
My form for comments looks something like this:
<form action="" method="post" id="comment-form" enctype="multipart/form-data">
<input type="file" name="file" id="file" multiple />
<textarea name="text"></textarea>
<button type="button" onclick="sendComment();">Send</button>
</form>
I tried using Javascript model to process the data and I was able to save the asset correctly, however only one. I couldn't access the other files in the model.
I tried solving it (and improving user experience) by using AJAX and a REST endpoint. I opted not to use the Nodes endpoint API, because I didn't know how to solve the permission issue. I know I can restrict access to REST for each role, but not based on ownership of the Post. So I created my own Java-based endpoint (copied from documentation).
In the sendComment() function in Javascript I create an object with properties like name, extension, mimeType, ..., and data. I read in the documentation that you should send the data using the Base64 format, so I used FileReader() to accomplish that:
var fileObject = {
// properties like name, extension, mimeType, ...
}
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
// this part is easy
};
xhttp.open("PUT", "http://localhost:8080/myApp/.rest/assets/v1/saveAsset", true);
xhttp.setRequestHeader("Content-type", "application/json");
var reader = new FileReader();
reader.onload = function() {
fileObject.data = reader.result;
// I also tried without the 'data:image/png;base64,' part by reader.result.split(",")[1];
xhttp.send(JSON.stringify(fileObject));
};
reader.readAsDataURL(file); //where file is the value of the input element.files[i]
In Java I created a POJO class that has the same properties as the javascript object. Including a String data.
The code for the endpoint looks like this:
public Response saveAsset(Asset file) {
// Asset is my custom POJO class
Session damSession;
Node asset;
Node resource;
try {
damSession = MgnlContext.getJCRSession("dam");
asset = damSession.getRootNode().addNode(file.getName(), "mgnl:asset");
asset.setProperty("name", file.getName());
asset.setProperty("type", file.getExtension());
resource = asset.addNode("jcr:content", "mgnl:resource");
InputStream dataStream = new ByteArrayInputStream(file.getData().getBytes());
ValueFactory vf = damSession.getValueFactory();
Binary dataBinary = vf.createBinary(dataStream);
resource.setProperty("jcr:data", dataBinary);
resource.setProperty("fileName", file.getName());
resource.setProperty("extension", file.getExtension());
resource.setProperty("size", file.getSize());
resource.setProperty("jcr:mimeType", file.getMimeType());
damSession.save();
return Response.ok(LinkUtil.createLink(asset)).build();
} catch (RepositoryException e) {
return Response.ok(e.getMessage()).build(); //I know it's not ok, but that's not important at the moment
}
}
The asset gets created, the properties get saved apart from the jcr:data. If I upload an image and then download it either by the link I get as a response or directly from the Assets app, it cannot be opened, I get the format is not supported message. The size is 0, image doesn't show in the Assets app, seems like the data is simply not there, or it's in the wrong format.
How can I send the file or the file data to the Java endpoint? And how should I receive it? Does anybody know what am I missing? I honestly don't know what else to do with it.
Thank you
The input stream had to be decoded from Base64.
InputStream dataStream = new ByteArrayInputStream(Base64.decodeBase64(file.getData().getBytes()));
...and it only took me less than 3 months.
Noticed it after going through the source code for REST module that for unmarshalling Binary Value it had to be encoded to Base64, so I tried decoding it and it started to work.
I'm working on Audio/Video upload and Task. Can somebody help me show to achieve this functionality in Angular JS?
We would need more details, what hae you tried, what type of backend (REST, SOAP, Web Service in general) you are using, in which language...
I did it with a Java RESTful server by, probably, not the smarter solution.
$scope.uploadVideo = function(){
// Obtaining the selected file. In case of many, the others will be from the position 1 of the array
var f = document.getElementById("videoInput").files[0];
console.log("====================>SIZE: "+f.size);
var name = f.name;
//Getting the file name and its extension
}
//Loading the file and passing the callback as a parameter
loadFile(f, function(data){
// The file consist on its name and bytes
var file={
name:name,
data:data
}
//Sending the video
servicioRest.postFile(file)
.then(function(){
//Whatever
})
.catch(function(err){
console.log("ERROR");
alert("ERROR: "+err);
});
});
};
//---------------------------------------------------- UTILS ----------------------------------------------
function loadFile(source, callBack){;
var r = new FileReader();
//Event that will be triggered when FileReader finish reading the file
r.onloadend = function(e){
var data = e.target.result;
// some chars cannot be sent through http requests. So we encode them in base64 to ensure we send the correct bytes
data=btoa(data);
console.log(data.length);
callBack(data);
//send you binary data via $http or $resource or do anything else with it
}
//Reading the file. When it ends, the event "onloadend", previously declared, will be triggered
r.readAsBinaryString(source);
}
Then, in the server, I decoded the bytes and create a file with them and that bytes... or save them in the database.. Whatever you want.
But I insist, we need more details to answer you correctly. It's impossible, at list for me, to answer you correctly with only that information
I am trying to send an email with an attachment in my Ionic app, using the Phonegap plugin found here. One of the features of this plugin is to attach a file or file as Base64.
The email is sending fine, but it never attaches a file so it makes me think im doing something wrong forming my string. Specifically, I'm attempting to create a CSV, and attach it as a string.
Here's what my call looks like:
if(window.plugins && window.plugins.emailComposer) {
window.plugins.emailComposer.showEmailComposerWithCallback(function(result) {
//success callback
},
"Feedback for your App", // Subject
"", // Body
["whatever#whatever.com"], // To
null, // CC
null, // BCC
false, // isHTML
null, // Attachments
[["filename1","data:text/csv;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/..."]] // Attachment Data
);
}
};
I've been struggling with a similar issue.
Looking in the EmailComposer source for Android the attachmentsData array is treated as follows:
JSONArray fileInformation = attachmentsData.getJSONArray(i);
String filename = fileInformation.getString(0);
String filedata = fileInformation.getString(1);
byte[] fileBytes = Base64.decode(filedata, 0);
So the data part should be pure base64 data. If you change your line:
[["filename1","data:text/csv;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CA...
to
[["filename1","iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/..."]]
you might find it works.
I am using WebRTC to get two clients communicated using peer.js
var peer = new Peer(
{
key: "XXX",
config: {"XXX": [{ url: "XXXXXXX" }]}
});
My main aim is to send file from one client to another. For that I am using following code:
$("#box").on("drop", function(e)
{
e.originalEvent.preventDefault();
var file = e.originalEvent.dataTransfer.files[0];
console.log(file);
connection.send(file);
});
On the receiving end I am using below code:
conn.on("data", function(data)
{
if (data.constructor === ArrayBuffer)
{
var dataView = new Uint8Array(data);
var dataBlob = new Blob([dataView]);
var reader = new window.FileReader();
reader.readAsText(dataBlob);
console.log(reader);
}
}
Now my problem is I want to get the file type so that I can save it in the proper format. I am using download.js to save the file.
It is not possible to get the type from the raw data except there is some file type/hint embedded in the data (e.g. ZIP, PDF). You should create you own protocol to send the filename as well.
What I did is to use the channel's protocol property to set the filename with extension to transfer these type of metadata information.
Note that a few weeks ago sending blobs wasn't fully supported in Chrome (at least in one of my example applications).
I am using the node-png library to make the png and then save it in the local directory but when I go to open it back up, it says that it does not exist. I want to either read in the data and send it out or just have the response send an <img> field with the picture. Here's what I have so far:
//write out img data
png.pack().pipe(dst);
//link to new image made
var link = fs.createReadStream('out.png'); //says that this does not exist
//write out response with img then delete file
response.writeHead(200, {"Content-Type": "image/png"});
response.end(link, 'binary');
Couldnt you just skip writing to file altogether?
var output = png.pack();
res.setHeader('Content-Type', 'image/png');
output.pipe(res);
If you do need to write it to disk simultaneously, refer to this answer:
https://stackoverflow.com/a/19561718/944006
If you need to write to disk FIRST and THEN read from that, you would do:
var output = png.pack();
output.pipe(dst, { end: false });
output.on('end', function(){
//Read your file and set your response here.
}
I didn't test any of this but that's the way piping works in general.