I'm uploading an image using AngularJS to my NodeJS server. But I have no idea how to display the image back to the user. The upload works fine, I can see the image on the server, but then how do I get it back to the client side to display it?
HTML:
<img ng-src="{{logo}}" class="col-sm-3" height="100" width="100">
<div id="dropzone" ng-file-drop="" ng-file-select="" ng-model="files" class="drop-box col-sm-9"
drag-over-class="dragover" ng-multiple="false" allow-dir="false"
accept=".jpg,.png"><b>Drop</b> image here or <b>click</b> to upload</div>
<div ng-no-file-drop>File Drag/Drop is not supported for this browser</div>
JS: (angular using ng-file-upload library)
$scope.upload = function (files) {
if (files && files.length) {
for (var i = 0; i < files.length; ++i) {
var file = files[i];
$upload.upload({
url: "api/uploadLogo",
file: file
}).success(function (data, status, headers, config) {
console.log("file " + config.file.name + " uploaded. Response: " + JSON.stringify(data));
$scope.logo = data;
});
}
}
};
In data in success, I get things like :
Am I doing something wrong? How am I supposed to do this ?
Try handing back the location of the file and input it into a img tag like
<img ng-show="data['imgUrl']" ng-src="{{data['imgUrl']}}">
EDIT:
Searching StackOverflow came back with a similar question:
Sending an image to the server after displaying it in the UI in Angular.
Hope it helps.
EDIT 2:
Based on a better understanding of the requirements from the comments my suggestion is to use an image tag <img ng-src="data:image/png;base64,{{logo}}" /> with a $scope.image = data in the controller.
This necessitates the return of a base64 encoded image file. Which would be done in node with var base64image = new Buffer(imageFile).toString('base64'). I use node here based on the tag of node.js but any language should be able to do base64 encoding.
Related
We're trying to upload a song (.mp3) file from a JSP frontend written in HTML / Javascript. We need to upload to our Java backend using websockets. Does anyone have any suggestions on how we would could go about doing this?
Currently we are doing something like this on our JSP file:
<h1>Please Choose a Song file</h1>
<form name = "JSONUploadForm">
<input type = "file" name="file" accept = ".mp3"/> <br/>
<input type = "button" value = "Click to upload!" name = "button" onClick = "submitSong();"/>
</form>
Then we have our javascript function submitSong()
function submitSong(){
var songStuffs = document.getElementById("file");
console.log(songStuffs); --> we get "null" here
sendMessage(songStuffs);
alert("song sent");
}
function sendMessage(val, string) {
socket.send(string);
return false;
}
Also, here is our connect to server function. However, this functions correctly.
function connectToServer() {
socket = new
WebSocket("ws://localhost:8080/Project/socket");
socket.onopen = function(event) {
console.log("connected!");
}
You can also see our server side (.java file):
#OnMessage
public void onMessage(String message, Session session) throws IOException, EncodeException {
FileWriter fw = new FileWriter(new File(songName + ".mp3"));
fw.write(song);
BufferedReader fr = new BufferedReader(new FileReader(songName + ".mp3"));
String data = fr.readLine();
System.out.println("Song: " + data); --> Here we get "song: null"
}
Any suggestions would be greatly appreciated!
In your code you have an error
"var songStuffs = document.getElementById("file");"
Your file input without id.
this will work "var songStuffs = document.querySelector("[name=file]");"
I prefer using querySelector, because it mo flexeble and works exactly like jquery query selectors)))
You do not need any form, for upload files.
Please read this article https://www.html5rocks.com/en/tutorials/websockets/basics/,
it will be useful for you (search words "blob" at the page)
Html
<input id="file" type = "file" name="file" accept = ".mp3"/>
Code
var fileInput = document.querySelector("#file");
fileInput.addEventListener("change",function(){
connection.send(fileInput.files[0]);
});
If you need to send file and fields, you have 3 variants
create JSON {"field1":"value1","field2":"value1",
"file":"base64"}
manualy create formdata and parse form data at the
server with some webform stuff (example
https://stackoverflow.com/a/47279216/5138198)
Firstly send JSON
data, secondly send a file
Try with this, If you have to upload file you should add enctype in form.
<form enctype="multipart/form-data">
<input type = "file" name="file" id="song" accept = ".mp3"/>
</form>
Update:
You can use simply WebSocketFileTransfer plugin to send your file. This plugin helps in with many features like Auth, progress status, file/blob compatibility.
var songStuffs = document.getElementById("song").files[0];
var transfer = new WebSocketFileTransfer({
url: 'ws://ip:port/path/to/upload_web_socket_server',
file: songStuffs,
progress: function(event) {
// Update the progress bar
},
success: function(event) {
// Do something
}
});
transfer.start();
Currently I am using the following approach where it is giving details of file but not the actual object it seems like one we get from in javascript/jQuery. Does any one having the clue how to get the file object from File URI /native URI from mobile ios/android filesystem using cordova and javascript?
Below is the snippet I am using currently..
window.resolveLocalFileSystemURL(
filepath,
function(fileEntry) {
fileEntry.file(
function(file) {
var reader = new FileReader();
reader.onloadend = function() {
var imgBlob = new Blob([this.result], {type: "image/jpeg"});
var uploadedFile = imgBlob;
uploadedFile.name = file.name;
alert("Importing Asset from Camera.. " + uploadedFile.name);
alert(uploadedFile.type);
alert(uploadedFile.size);
importAsset(uploadedFile);
};
reader.readAsArrayBuffer(file);
},
function(error) { alert("Error in fileEntry.file():" + error) })
},
function(error) { alert("Error in window.resolveLocalFileSystemURL():" + error) }
);
Note: FileTransfer.upload() will not work in my case.
Above snippet I am using after taking from Append image file to form data - Cordova/Angular after going through the existing Q&A from #SO
Base64 Image Upload will work both in iOS/Android as I have tried:
As for iOS There is only one way to show image is using base64 format.You can use cordova-camera-plugin to to generate base64 image and put on img tag of HTML.I have set the flag to get data in jpeg,base64 in camera plugin.
<img id="cardImg">
Store the base64 image in javascript variable as:
var imgdata=data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
Then Simply pass data to img tag of HTML as:
cardImg.src=imgdata;
Done!
I want to load the PDF file dynamically and show on browser. PDF file is created on the fly when user clicks on button and the filename has timestamp in it. So i cannot give the PDF filename in the html code as shown below as it changes based on the timestamp(PDF file name is given along with the timestamp when it was created as shown in below spring controller).
Below is the code.
html code:
<div ng-controller="generatePDFController">
<button ng-click="generatePDF()">Re-Generate PDF</button>
<object data="C:/allFiles/PDFFiles/spreadDetails.pdf" type="application/pdf" width="100%" height="100%">
<iframe src="C:/allFiles/PDFFiles/spreadDetails.pdf" width="100%" height="100%" style="border: none;">
This browser does not support PDFs.
Download PDF
</iframe>
</object>
</div>
js code:
app.controller('generatePDFController', function($scope, MyService) {
$scope.generatePDF = function() {
MyService.createPDF().then(
function(response) {
$scope.pdf = response;
},
function(errResponse) {
});
}
});
//service call
_myService.createPDF = function() {
var deferred = $q.defer();
var repUrl = sURL + '/allDataGeneration/generatePDF.form';
$http.get(repUrl)
.then(
function(response) {
deferred.resolve(response.data);
},
function(errResponse) {});
return deferred.promise;
}
spring controller:
#RequestMapping(value = "/generatePDF", method = RequestMethod.GET)
public# ResponseBody List < MyDTO > generatePDF() {
List < MyDTO > response = service.getAllData();
//create PDF and write the response in it
createPDFFile(response);
return response;
}
void createPDFFile(List < MyDTO > res) {
String FILE_PATH = "C:\\allFiles\\PDFFiles\\spreadDetails";
String FILE_EXTENSION = "pdf";
DateFormat df = new SimpleDateFormat("MM-dd-yyyy hh-mm-ssa");
String filename = null;
try {
filename = FILE_PATH + df.format(new Date()) + "." + FILE_EXTENSION;
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(filename);
System.out.println("-----filename------------ " + filename); //PDF file is created successfully
//spreadDetails07-13-2017 02-59-51PM ,when user clicks on GeneratePDF in UI, it hits this controller and generates the PDF
//logic to write the data inside PDF file
}
The above shown code is the complete flow of my sample application. Now when user clicks on Re-Generate PDF button, it comes to above mentioned spring controller creates a file with timestamp and writes the data in it.How to pass the newly created pdf filename to the html code <object data="C:/allFiles/PDFFiles/spreadDetails.pdf" .. so that when pdf file is created it dynamically loads and show on UI.
---EDITED---
Please see the above edited code. createPDF(List<MyDTO>) is a new method in which i'm creating a pdf file and writing the content. I will be reusing this method.
Try to follow these steps :
Change the signature of the Java method generatePDF() in order to return a String representing the name of your file. This gives you the possibility to pass the name of the file to your JavaScript ;
In your controller, do $scope.pdfName = response. This way the name of the file is store the variable $scope.pdfName ;
Last step, replace <object data="C:/allFiles/PDFFiles/spreadDetails.pdf" ...> by <object data="{$scope.pdfName}" ...>
This should work.
Marine
EDIT given your own edit :
Your method generatePdf() is incorrect : you wrote that it must return a List<MyDto> but the keyword return is nowhere.
Do you really need to return he object List<MyDto> ? In any case, you need to return the name of the file to be able to use it in your JavaScript. So, you have two solutions : either this method only returns a String representing the name of the PDF, or it returns an object with two fields, one String and one List<MyDto>. In this second cas, you will need to do
$scope.pdfName = response.fieldContainingTheNameOfTheFile.
I am using "File Upload" control and C# coding (backend) for uploading files(.jpeg/.png/.pdf) in my web application.
The files uploaded through this control should be saved in the server.
Everything is working fine but the problem i am facing is when a file type of xlsx or doc is been saved and the extension of that file is changed to .png or .jpeg and is being uploaded it is being uploaded into the server without any error.
While I am trying to open that image or pdf file in server it is as usually showing the error message the file cant be opened.
I have done extension validation but it does not show any effect here in this case.
Can anyone help me to get rid of this problem.(Either C# coding or Jquery Or javascript will do)
Here is how finally able to get the validation as I need using "Header codes":
System.IO.BinaryReader r = new System.IO.BinaryReader(FileUpload1.PostedFile.InputStream);
string fileclass = "";
byte buffer;
try
{
buffer = r.ReadByte();
fileclass = buffer.ToString();
buffer = r.ReadByte();
fileclass += buffer.ToString();
}
catch
{
}
r.Close();
if (fileclass != "3780" || fileclass != "255216" || fileclass != "13780") /*Header codes (3780-PDF);(255216-JPG,JPEG);(13780-PNG)*/
{
/*Your code goes here(things to do with the file uploaded)*/
}
For getting values for other file formats try uploading the file and set break point and get the header code.
Can you show us how your validation looks like ?!
There is two way to check the extension of a file that you are uploading. It should be like this following :
//In your aspx file :
<asp:FileUpload ID="FileUploadControl" runat="server"/>
<asp:Button runat="server" id="Btn_Upload" text="Upload" onclick="Btn_Upload_Click" />
//In your aspx.cs file :
// First soluce
protected void Btn_Upload_Click(object sender, EventArgs e)
{
if (FileUploadControl.PostedFile.ContentType != "application/pdf")
{
//Not an PDF
}
}
// Second soluce :
protected void Btn_Upload_Click(object sender, EventArgs e)
{
string extension = Path.GetExtension(FileUploadControl.PostedFile.FileName);
if (extension != ".pdf")
{
//Not an PDF
}
}
Of course, on these code sample you can add for exception for JPEG / PNG / ...
Edit, Updated
But my problem is the extension is a proper one which i need to upload
but the file type is not i mean an excel sheet can be saved with
extension jpeg
You can use FileReader, .readAsBinaryString() to check for file headers; e.g, JFIF for .jpeg, .jpg; PNG for .png; PDF for .pdf; RegExp.prototype.test() with RegExp /JFIF|PNG|PDF/
Use accept attribute at <input type="file"> element with value set to ".jpeg,.jpg, .png,.pdf" to exclude files with extensions other than .jpeg, .jpg, .png or .pdf from being able to be selected by user at Choose File dialog.
document.querySelector("input[type=file]")
.addEventListener("change", function(e) {
console.log(e.target.files[0].type);
var reader = new FileReader();
reader.onload = function(event) {
console.log(event.target.result
, /JFIF|PNG|PDF/.test(event.target.result))
}
reader.readAsBinaryString(e.target.files[0])
})
<input type="file" accept=".jpeg,.jpg,.png,.pdf" />
There are many image format, like webp for example why not support them all?
You can convert them client side before you upload them using canvas...
function convertImage(image, mimetype, quality) {
return new Promise(function(resolve){
var canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
canvas.getContext("2d").drawImage(image, 0, 0)
canvas.toBlob(resolve, mimetype, quality)
})
}
if(input.files[0].type === 'application/pdf') {
// upload directly (not a image)
} else {
var img = new Image
img.onerror = function() { /* not an image */}
img.onload = function() {
convertImage(img, 'image/png', 1).then(function(blob){
// upload the converted image
fetch('upload', {method: 'POST', body: blob})
})
}
img.src = URL.createObjectURL(input.files[0])
}
then you use this to help filter out the accepted files you want
<input type="file" accept="application/pdf, image/*">
I am exposing a PDF file in the browser like:
//html
<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 550px;"></object>
//angular controller
$http.get('/api/,
{ responseType: 'arraybuffer' })
.success(function (response) {
var file = new Blob([(response)], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
$scope.content = $sce.trustAsResourceUrl(fileURL);
});
This works fine getting the Stream/Blob of the PDF back and exposing it in the browser, but I wish to not show the print/download/rotate bar that is shown at the top:
Any idea how this can be achieved? If I have to convert the PDF to a series of images is there a good way to do that from a BLOB form either on my client or server side?