I am trying to preview selected file in Angular 9.
<h3>Angular 9 Image Preview before Upload:</h3>
<input #file type="file" accept='image/*' (change)="preview(file.files)" />
<img [src]="imgURL" height="200" *ngIf="imgURL">
And ts file is
preview(files) {
if (files.length === 0)
return;
var mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
let message = "Only images are supported.";
return;
}
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
this.imgURL = _event.target.result;
}
}
But when first time i select the file i dont get any display, next time when i upload a file i get the display of last file i selected. I saw many working example with the same concept on internet, Is there any change in file upload login for new angular version i.e Angular 9.
After some RnD got the solution. We need to call detectChanges() after the imgUrl is changed.
preview(files) {
if (files.length === 0)
return;
var mimeType = files[0].type;
if (mimeType.match(/image\/*/) == null) {
let message = "Only images are supported.";
return;
}
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = (_event) => {
this.imgURL = _event.target.result;
this.ref.detectChanges();
}
}
the above solution worked fine for me.
Related
I have a file upload control in my angular app where user could upload any type of file except a few ones .exe, .sql etc
<input type="file" id="file" #file (change)="fileUploadHandler($event)" multiple>
fileupload.component.ts
fileUploadHandler(event: Event) {
const inputElement = event.target as HTMLInputElement;
if (inputElement.files && inputElement.files?.length) {
_each(inputElement.files, (_file) => {
const fileSize = _file.size;
if (fileSize < this.MAX_DOC_SIZE) {
const fileName = _file.name?.trim();
const doc = new Document();
doc.name = fileName;
doc.extension = fileName.slice(fileName.lastIndexOf('.') + 1);
doc.size = fileSize;
this.docs.push(doc);
}
});
}}
This list the files in UI as below
Now what I need is that when user click on a file, that file should open in a new tab
how can I do this?
On googling I see suggestions to use FileReader & gave a try
_each(inputElement.files, (_file) => {
const reader = new FileReader();
const data = reader.readAsDataURL(_file);
console.log(data) // nothing is printed on console
Please suggest. Thanks!
You have to enhance the code a little bit (as #mav-raj also stated). In Angular you can use the following:
_each(inputElement.files, (_file) => {
const reader = new FileReader();
reader.onloadend = ((result) => {
console.log(result) // now something will be printed!
});
reader.readAsDataURL(_file);
})
I've got an app that, since 5 years now, that displays an offline map by reading from a folder embed in it ("assets").
Since Android 11, it's impossible to read from ApplicationStorage (Error #3001: File or directory access denied), so I'm trying to copy the folder from applicationStorage to "Documents".
What I did :
source = File.applicationDirectory.resolvePath("assets/maps");
destination = File.documentsDirectory.resolvePath("Documents/www");
source.addEventListener(Event.COMPLETE, onMapCopyComplete);
source.copyToAsync(destination, false);
function onMapCopyComplete(e: Event): void {
source.removeEventListener(Event.COMPLETE, onMapCopyComplete);
log("onMapCopyComplete()");
}
I've got a return onMapCopyComplete() but when I'm looking in InternalStorage/Documents of my phone I've got the folders but all are empty... None of the files were copy..
PrintScreen computer vs phone
To read the files, here's what I'm doing :
function startMapsView()
{
var indexFile:File = File.applicationStorageDirectory.resolvePath("www/index.html");
if (!indexFile.exists)
{
log("startMapsView() Index file not found, Please check www/index.html");
return;
}
// Create StageWebView
stageWebView = new StageWebView(isMobile); // Set to TRUE for System's NativeWebView, FALSE is for AIR's WebView
stageWebView.stage = stage;
stageWebView.viewPort = new Rectangle(0, iOSStatusBarHeight + headerBarHeight, deviceStageSize.width, deviceStageSize.height - (iOSStatusBarHeight + headerBarHeight + footerBarHeight));
stageWebView.addEventListener(flash.events.Event.COMPLETE, onStageWebViewLoaded);
stageWebView.addEventListener(flash.events.ErrorEvent.ERROR, onStageWebViewError);
stageWebView.addEventListener(LocationChangeEvent.LOCATION_CHANGING, onStageWebViewLocationChanging);
// Load Map URL
stageWebView.loadURL(mapsURL);
}
And mapsURL is define by :
function setMapsURL(doNotEnableButtons: Boolean = false): void {
var indexFile: File = File.documentsDirectory.resolvePath("Documents/www/index.html");
trace("indexFile url is = "+indexFile.url);
if (!indexFile.exists) {
log("setMapsURL() Index file not found, Please check www/index.html");
return;
}
var assetsDir: File;
if (!useOnlineMaps) {
assetsDir = new File(destination.resolvePath("index.html").nativePath);
} else {
assetsDir = new File(destination.resolvePath("onlineMaps.html").nativePath);
mySavedData.data.onlineMapChoosen = false;
}
mapsURL = assetsDir.url;
log("setMapsURL() " + mapsURL);
if (!doNotEnableButtons) enableMapButtons();
}
Angular v 9.0.7
i have this input in my html which is gets triggered by the button:
<input #file (change)="importFile($event)" accept="audio/*, image/*, video/*" hidden type="file">
<button class="msg-npt-btn msg-npt-fl-icon" (click)="file.click()"></button>
it works for the first time i select a file but after that importFile() get called every second or third time if i select another file.
importFile(event) {
alert("import"); //test
if (event.target.files.length == 0) {
console.log("No file selected!");
return
}
this.selectedFile = event.target.files[0];
...
This is example how to load images may will it help.
importFile(event): void {
alert('import'); // test
const reader = new FileReader();
if (event.target.files.length === 0) {
console.log('No file selected!');
return;
}
reader.readAsDataURL(event.target.files[0]);
reader.onload = ((r) => {
this.selectedFile = r.target.result;
});
}
I'm trying to implement copying multiple images from adobe illustrator and pasting it in web page to upload. I could achieve the same for single image but when I copy multiple images, all the images together act as single image.
Below is the code
<mat-card class="imageUpload" (paste)=handlePaste($event)></mat-card>
handlePaste(event: any) {
const items = (event.clipboardData ||
event.originalEvent.clipboardData).items;
let blob = null;
for (const item of items) {
if (item.type.indexOf('image') === 0) {
blob = item.getAsFile();
const reader = new FileReader();
reader.onload = (evt: any) => {
this.onUpload("blob.name", evt.target.result);
};
reader.readAsDataURL(blob);
}
}
}
I have made me a simple file field:
<input type="file" name="pictures_array[]" multiple accept="image/*" id="page_pictures_array" />
and some HTML5 File API code to list the files:
$('.page-form #page_pictures_array').change(function(evt) {
var file, files, reader, _i, _len;
files = evt.target.files;
console.log(files);
$('#file-list').empty();
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
reader = new window.FileReader;
reader.onload = (function(file) {
return function(e) {
var src;
src = e.target.result;
return $("<li>" + file.name + " - " + file.size + " bytes</li>").prepend($('<img/>', {
src: src,
"class": 'thumb'
})).appendTo($('#file-list'));
};
})(file);
reader.readAsDataURL(file);
}
});
(cf. here)
However, since I expect my users to be very stupid indeed, I am sure they will choose one file, then click on the upload field another time to choose the next. However, the list of the <input type="file"> is reset each time with the newly chosen images.
How can I make sure the new files are appended to the <input>'s array so I don't get flooded with angry user comments?
I'm also looking for an answer to this, I think others already do that.
But if you look at the filelist W3 reference http://www.w3.org/TR/FileAPI/#dfn-filelist it says that its readonly....
Edit: It's a big code now, with some improvements, that make the copy/paste difficult. But I started to create one variable that saves all the tmp files.
var tmp_files = new Array();
Then when I add a new file I push the file to that array like this
tmp_files.push(file);
After all the insertions/removals (I have another var to save the deletions) when the user clicks to send the files I have this code that makes the formdata with the files I want
var data = new FormData(); var count = 0;
$.each(tmp_files, function(i, file){
if(del_files.indexOf(file.name)== -1){
data.append(count, file);
count++;
}
});
Then I just send the var data thru ajax and save them.
You can get them using $data = $_FILES;
Hope this helps you.