AngularJS + Firebase Upload profile image - javascript

I have a JavaScript image uploader which will upload an image and give me the image src. I need to save this value in my FireBase DB for the current user being created.
I tried outputting the img.src to a hidden input but that didn't seem to work. Like so:
$('.userImageValue').val(img.src);
<input class="userImageValue" ng-model="data.userImage" style="display: none;">
I just figured out if I change the value once it is added to the invisible input it works. So how can I best make the input "register" after the src value is inserted?
Here is the controller where a new user is created.
$scope.list = $firebaseArray(new Firebase("https://my-db.firebaseio.com/users"));
// Create user button
$scope.add_new_user = function() {
console.log($scope.data);
$scope.list.$add($scope.data);
$scope.data = {};
}
This is an input on the page which currently works with the above code and saves a new field for the current user being created.
<input id="firstname" type="text" ng-model="data.firstname" class="form-control" placeholder="First name">
This is the part I am stuck on I need to save the value of img.src from the code below as a new field in the FireBase DB for the user currently being created.
var userImageUploader = document.getElementById('userImageUploader');
userImageUploader.addEventListener('change', function(e) {
var file = userImageUploader.files[0];
var imageType = /image.*/;
if (file.type.match(imageType)) {
var reader = new FileReader();
reader.onload = function(e) {
var img = new Image();
img.src = reader.result;
}
reader.readAsDataURL(file);
}
});
I hope that makes sense and thank you in advanced!

You may want to consider using Parse for the image portion.
1) it also has a free tier but with much larger storage than the firebase free tier, which will quickly be exhausted by images.
2) it has better tools for images imo.

Related

Displaying preview of multiple selected files in Angular

I am kind of new to Angular and right now I am trying to select multiple files and display their preview before uploading them to server.
My below code works fine if there are multiple files but selected separately, hovewer while trying to select multiple images at once, only the last one is rendered. I checked with console.log and while selecting multiple files at once the reader.result of the previous files except the last one is always null ever though the reader.onload is executing (the object is also inserted into the array, but without the image url).
I want to be able to also remove the selected files, so both files and their imagesUrl are kept in an FileWithImage object to keep the right order of their previews.
component.ts:
onFilesSelected(event: any): void {
this.selectedFiles = event.target.files;
for (let i = 0; i < this.selectedFiles.length; i++) {
let fileWithImage: FileWithImage = {
imageUrl: '',
file: this.selectedFiles[i],
};
var reader = new FileReader();
reader.readAsDataURL(fileWithImage.file);
reader.onload = (event) => {
fileWithImage.imageUrl = reader.result;
console.log(fileWithImage.file.name);
console.log(fileWithImage.imageUrl);
this.filesWithImages.push(fileWithImage);
};
}
}
component.html (selecting and displaying images):
<button
type="button"
mat-raised-button
(click)="fileInput.click()"
class="button"
>
Choose File
</button>
<input
hidden
(change)="onFilesSelected($event)"
#fileInput
type="file"
accept="image/*"
multiple="multiple"
/>
<div *ngFor="let file of filesWithImages" class="images">
<img
[src]="file.imageUrl"
height="10%"
width="10%"
*ngIf="file.imageUrl"
/>
</div>
I tried blocking the loop untill the reader.onload is executed with a use of a flag, but it did not work.
I also tried to get the url directly from a method:
createImageUrl(file: File): any {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (event) => {
return reader.result;
};
}
and call it in [src] of an image tag in html, but it made my program crash.
The main problem is probably why the result of reader is null for the first few files and only the last one is properly displayed. Can someone help me to find the cause of this problem?
Try changing reader variable to local scope.
Change
var reader = new FileReader();
to
let reader = new FileReader();

I want to extract a string from a text file and output it as a text file again

I want to extract a string from a text file, convert it to a word scrambler (I figured out that part) and output it in another text file.
I found some code to input a text file and extract the text:
<html>
<h4>Select un file con .txt extension</h4>
<input type="file" id="myFile" accept=".txt" />
<br /><br />
<div id="output"></div>
<script>
var input = document.getElementById("myFile");
var output = document.getElementById("output");
input.addEventListener("change", function () {
if (this.files && this.files[0]) {
var myFile = this.files[0];
var reader = new FileReader();
reader.addEventListener("load", function (e) {
output.textContent = e.target.result;
});
reader.readAsText(myFile);
}
});
</script>
</html>
Input text and extract a text file
<html>
<div>
<input type="text" id="txt" placeholder="Write Here" />
</div>
<div>
<input type="button"id="bt"value="Save in a File"onclick="saveFile()"/>
</div>
<script>
let saveFile = () => {
const testo = document.getElementById("txt");
let data = testo.value;
const textToBLOB = new Blob([data], { type: "text/plain" });
const sFileName = "Testo.txt";
let newLink = document.createElement("a");
newLink.download = sFileName;
newLink.href = window.URL.createObjectURL(textToBLOB);
newLink.style.display = "none";
document.body.appendChild(newLink);
newLink.click();
};
</script>
</html>
But I don't know how to output a string in the first code or how to connect it to the second code. Could someone please show me how to do it or explain how these codes work so that I could try to do it myself in JavaScript?
I will comment each line of JavaScript, that should help you understand.
<script>
/*This creates a global variable with the HTML element input in it. */
var input = document.getElementById("myFile");
/*This creates a global variable with the HTML element div with id output in it. */
var output = document.getElementById("output");
/* this 2 lines are used to set the source and the destination.
The first will get where you put your file, in this case it's the input element.
The second will get the div which content will be replaced by the content of your txt file. */
/* Here we tell to our input element to do something special when his value changes.
A change will occur for example when a user will chose a file.*/
input.addEventListener("change", function () {
/* First thing we do is checking if this.files exists and this.files[0] aswell.
they might not exist if the change is going from a file (hello.txt) to no file at all */
if (this.files && this.files[0]) {
/* Since we can chose more than one file by shift clicking multiple files, here we ensure that we only take the first one set. */
var myFile = this.files[0];
/* FileReader is the Object in the JavaScript standard that has the capabilities to read and get informations about files (content, size, creation date, etc) */
var reader = new FileReader();
/* Here we give the instruction for the FileReader we created, we tell it that when it loads, it should do some stuff. The load event is fired when the FileReader reads a file. In our case this hasn't happened yet, but as soon as it will this function will fire. */
reader.addEventListener("load", function (e) {
/* What we do here is take the result of the fileReader and put it inside our output div to display it to the users. This is where you could do your scrambling and maybe save the result in a variable ? */
output.textContent = e.target.result;
});
/* This is where we tell the FileReader to open and get the content of the file. This will fire the load event and get the function above to execute its code. */
reader.readAsText(myFile);
}
});
</script>
With this I hope you'll be able to understand the first part of this code. Try putting the second part of your code instead of output.textContent and replacing data with e.target.result, that should do what you wish, but I'll let you figure it out by yourself first, comment on this answer if you need further help !
Here's a codepen with working and commented code:
https://codepen.io/MattDirty/pen/eYZVWyK

Get the image as file in angular

I am making angular application with image upload option which has the,
Html :
<label class="hoverable" for="fileInput">
<img [src]="url ? url : avatarImage">
<div class="hover-text">Choose file</div>
<div class="background"></div>
</label>
<br/>
<input id="fileInput" type='file' (change)="onSelectFile($event)">
<button *ngIf="url" (click)="delete()" >delete</button>
<img (click)="uploadPersonaImage($event)" class="avatar-images" src="https://www.w3schools.com/howto/img_avatar.png">
<img (click)="uploadPersonaImage($event)" class="avatar-images" src="https://www.w3schools.com/howto/img_avatar2.png">
Here what i am having is if the user clicks over the image he can select and update whatever image he has in local.
Same way if the user was not interested to update the profile image but interested to select any of the avatar image as per his/her wish which i have given like,
<img (click)="uploadPersonaImage($event)" class="avatar-images" src="https://www.w3schools.com/howto/img_avatar.png">
<img (click)="uploadPersonaImage($event)" class="avatar-images" src="https://www.w3schools.com/howto/img_avatar2.png">
And in ts made something like this,
uploadPersonaImage(e) {
this.url = e.target.src;
}
So on the click function the src that comes from the event.target was set to this.url..
But i need to convert it as file.. Because i need to send it as file to the service call so i need to update the avatar image.
So please help me to convert the avatar image selected/clicked by the user to the file/formdata so that it can be sent to the service as file format and can be updated as user selected image..
Example: https://stackblitz.com/edit/angular-file-upload-preview-85v9bg
You can use FormData to attach the read file and send to the API.
onSelectFile(event) {
if (event.target.files && event.target.files[0]) {
this.uploadToServer(event.target.files[0]);
... rest of the code
}
uploadToServer(file) {
let formData: FormData = new FormData();
formData.append('fileName', file);
// call your api service to send it to server, send formData
}
EDIT:
Try this out if you have no option to touch onSelectFile() or trigger a different function when you upload the file.
_url = ''
set url(val) {
this._url = val;
if (val) {
this.dataURLtoFile(val);
}
}
get url() {
return this._url;
}
uploadedImage: File ;
dataURLtoFile(dataurl) {
const arr = dataurl.split(',');
const mime = arr[0].match(/:(.*?);/)[1];
const imageExtension = mime.split('/')[1];
const bstr = atob(arr[1]);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
this.uploadedImage = new File([u8arr], `uploaded.${imageExtension}`);
}
On your API call, maybe when you click on a button,
uploadPersonaImage(e) {
// this.apiService.someMethod(this.uploadedImage);
}
If you want to trigger the API call just when you upload the image, add the code of dataURLtoFile() to uploadPersonaImage() and call uploadPersonaImage() from url setter
Clarification
Do you understand what does event.target.src mean (considering e as event)?
Here event means the click/change event you triggered when you
clicked onto upload photo.
event.target means the DOM element on which the event took place.
event.target.src will give you the src attribute value of the
DOM element on which you triggered the change event.
Now, you say won't it work? No, it won't because the element which you clicked is an HTMLInputElement but the src resides under the image in under the label tag. And how are you intending to call uploadPersonaImage()? what calls your method? You haven't answered that even after asking so many times.
In my last edit, I have added code under the setter of the url which will convert the dataUrlFile to an actual File, It completely depends on your server how you want to store the file. As a file or as a dataUrl? If you want to send it as a file then follow the conversions I added in the answer if you want to save as dataUrl then directly save the content of this.url on your API call.

Angular upload image and display to user

Id like to implement a UI where the user selects an image and that image is instantly displayed back to them for review. The user would have to click "submit" to upload/save the image to their profile.
I am having issues with the "instantly display back to the user part".
I am using angular FormData with the following markup & controller:
MARKUP
<input id="chooseFile" type="file" file-model="picFile" />
<img src="{{uploadedImage}}" /> <!-- this populates with filename but what is the path?? -->
CONTROLLER
angular.element('#chooseFile').change(function(){
var file = $scope.picFile; // this comes up "undefined" since file is still uploading when this is fired
$scope.uploadedImage = file.name;
});
I have 2 primary issues with the above code (described in comments):
1) In the controller, file comes up undefined obviously because even the smallest file takes >0s to upload while the callback is fired pretty much instantaneously. I got it work using $timeout but thats a bit of a lame hack. How can I have the callback wait until the file is uploaded??
2) The idea is to upload the file and display it in the img tag using Angular's data-binding. This works in that src is populated with the filename, but what is the path of the img. Some temporary location in cache or something?? Obviously I havent set a path to move the file yet.
Any help appreciated!
I also needed this feature, some how I manage to display image instantly.
angular.module('HelloWorldApp', [])
.controller('HelloWorldController', function($scope) {
$scope.uploadavtar = function(files) {
//var fd = new FormData();
//Take the first selected file
//fd.append("file", files[0]);
var imagefile = document.querySelector('#file');
if (imagefile.files && imagefile.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#temp_image')
.attr('src', e.target.result);
};
reader.readAsDataURL(imagefile.files[0]);
this.imagefile = imagefile.files[0];
}else{
console.log("Image not selected");
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="HelloWorldApp">
<div ng-controller="HelloWorldController">
<input type="file" id="file" onchange="angular.element(this).scope().uploadavtar(this.files)"/>
</div>
<img src="" id="temp_image" width="100">
<div>
</div>
</div>
I was using laravel + Angularjs so another related post to store image is : https://stackoverflow.com/a/34830307/2815635

How do I upload and process a file in Javascript?

I am creating a small html5 app that will allow users to change color properties of some elements. I want to give the user the option to save their changes and then upload them on later occasion (without registration). For this, I added a button that produces a text file of their properties, I want to add a button that will allow them to upload the file, I created a file picker dialog,
<label>
<input class="button"
type="file"
name="input-name"
style="display:none;"
onchange="read(event)"/>
<span id="input-file" >Select File</span>
</label>
But I can't figure how do I open this file in javascript and process its content. I know this should be similar to this
function read(evt){
var file = document.getElementById("input-file");
//checking for file reader
if (window.File && window.FileReader && window.FileList && window.Blob){
var r = new FileReader();
r.readAsText(file);
} else{
alert("Browser not supported");
}
}
But this doesn't work because file above is not the path to the file but the object. How do I get the path to the file? Is there a better way to do this?
You can read files via the File API, but you can't save them. You can create windows containing the text you want to save and then let the user save it, but it's a pain both when saving and loading.
Fortunately, for what you're talking about, you don't want files.
Instead, store the color preferences in web storage, specifically localStorage:
Loading (e.g., on page load or whenever):
var savedColor = localStorage.getItem("saved-color");
if (savedColor == null) {
// There wasn't one, use a default
}
Saving:
localStorage.setItem("saved-color", savedColor);
(localStorage in the above isn't a placeholder or anything; it's a global that's present on browsers that support local storage, which is [just about all of them2.)
Web storage values are always strings. You can use JSON if you need to store complex things.
Assuming your text file is in JSON (stringified format), i.e. your file.txt contains {"primary":"green","secondary":"#FF0000"}
<input type="file" id="file-picker" accept="text/plain" />
/*
Assuming JSON format in the text file - e.g:
var colors = {
primary: 'green',
secondary: '#FF0000'
}
JSON.stringify(colors);
output: '{"primary":"green","secondary":"#FF0000"}'
*/
var fileInput = document.querySelector('#file-picker');
function readFileJSON(file) {
return new Promise(function(resolve) {
var reader = new FileReader();
reader.onload = function(e) {
try {
resolve(JSON.parse(e.target.result));
} catch(ex) {
throw ex;
}
};
reader.readAsText(file);
});
}
fileInput.addEventListener('change', function(e) {
var file = e.target.files.item(0);
if (!file) {
return;
}
readFileJSON(file).then(function(colors) {
console.log('Colors:', colors);
});
});
JSBIN: https://jsbin.com/weriguhato/edit?html,js,output

Categories