Read local file in angular 8 - javascript

I had a requirement of reading users data from file, the file can be of any format(.csv, .xls, ...)
Users data looks like
Name Email Number Image
Yaswanth yas....#gmail.com 0123456789 file:///home/yash/Desktop/.....jpg
When i reach the image value cells i should pick the image file from local path and convert to base64 but i was not able to read rather i get the following error
Not allowed to load local resource
Later i thought i could have one hidden input file and dynamically set the input value and have onchange even but for security reasons the input type file is read only so dropped my idea and trying with FileReader
Here is the code which i tried
changeListener($event,uploadType) : void {
this.readThis($event.target,uploadType);
}
readThis(inputValue: any,uploadType: any): void {
if(uploadType === 'image') {
}
if(uploadType === 'file') {
var file:File = inputValue.files[0];
this.readThisFile(inputValue);
}
}
readThisFile(inputValue: any): void {
const target: DataTransfer = <DataTransfer>(inputValue);
if (target.files.length !== 1) throw new Error('Cannot use multiple files');
const reader: FileReader = new FileReader();
reader.onload = (e: any) => {
/* read workbook */
const bstr: string = e.target.result;
const wb: XLSX.WorkBook = XLSX.read(bstr, { type: 'binary' });
/* grab first sheet */
const wsname: string = wb.SheetNames[0];
const ws: XLSX.WorkSheet = wb.Sheets[wsname];
/* save data */
this.data = <AOA>(XLSX.utils.sheet_to_json(ws));
console.log(this.data);
this.uploadData(this.data)
};
reader.readAsBinaryString(target.files[0]);
}
uploadData(dataToUpload:any[]) {
var doublemulUserList = []
for (let index = 1; index <= dataToUpload.length; index++) {
this.userObject = {
"Name": "",
"Email": "",
"Number": "",
"Image": ""
};
this.userObject.Name = dataToUpload[index-1]['Name'];
this.userObject.Email = dataToUpload[index-1]['Email']
this.userObject.Number = dataToUpload[index-1]['Number']
var xhr = new XMLHttpRequest();
xhr.open("GET", dataToUpload[index-1]['Image'], true);
xhr.responseType = "blob";
xhr.onload = function (e) {
console.log(this.response);
var reader = new FileReader();
reader.onload = function(event) {
var res = event.target.result;
console.log(res)
}
var file = this.response;
reader.readAsDataURL(file)
};
xhr.send()
}
}
Can some one share some links or an idea on how to go about this problem.

Related

JS FileReader ArrayBuffer to Byte[] to pass contents of a file

I have a file upload area in my application, it allows uploads of images, .doc, .docx and pdf.
I need to pass the contents of the file in a byte[] to my api so that it can store the file.
I have tried to convert from ArrayBuffer to Uint8Array but i have not been successful.
Here is my code for reading the file and obtaiing the required information
Any help would be appreciated.
let myFile = ev.target.files[0];
if(myFile.size > 0){
let reader = new FileReader();
var fileByteArray = [];
reader.readAsArrayBuffer(myFile);
reader.onloadend = (ev) => {
var uintArray = new Uint8Array(reader.result.toString().length);
//var arrayBuffer = new ArrayBuffer(reader.result);
//var array = new Uint8Array(arrayBuffer);
let resourceModel = new AddForumThreadResourceRequestModel({
contentType: myFile.type,
fileName: myFile.name,
fileContent: uintArray
});
console.log(resourceModel);
this.forumApi.AddThreadResource(resourceModel).subscribe(
data => {
if(data != null || data == true){
this.errorCtrl.presentToast("New resource has been added to the thread");
}
});
}
Try to use argument of load event:
reader.onload = (e) => {
var uintArray = new Uint8Array(reader.result);
let resourceModel = new AddForumThreadResourceRequestModel({
contentType: myFile.type,
fileName: myFile.name,
fileContent: uintArray
});
console.log(resourceModel);
this.forumApi.AddThreadResource(resourceModel)
.subscribe( data => {
if(data != null || data == true){
this.errorCtrl.presentToast("New resource has been added to the thread");
}
});

How to convert a image src from a blob string to data URI

I have a page where the user can paste an image into a content editable div. When I get the image the src returns a string. When I look in debug tools this is what I see:
<img src="blob:http://www.example.com/3955202440-AeFf-4a9e-b82c-cae3822d96d4"/>
How do I convert that to a base 64 string?
Here is the test script, http://jsfiddle.net/bt7BU/824/.
// We start by checking if the browser supports the
// Clipboard object. If not, we need to create a
// contenteditable element that catches all pasted data
if (!window.Clipboard) {
var pasteCatcher = document.createElement("div");
// Firefox allows images to be pasted into contenteditable elements
pasteCatcher.setAttribute("contenteditable", "");
// We can hide the element and append it to the body,
pasteCatcher.style.opacity = 0.5;
document.body.appendChild(pasteCatcher);
// as long as we make sure it is always in focus
pasteCatcher.focus();
document.addEventListener("click", function() { pasteCatcher.focus(); });
}
// Add the paste event listener
window.addEventListener("paste", pasteHandler);
/* Handle paste events */
function pasteHandler(e) {
// We need to check if event.clipboardData is supported (Chrome)
if (e.clipboardData) {
// Get the items from the clipboard
var items = e.clipboardData.items || e.clipboardData.files;
var itemcount = items ? items.length : 0;
pasteArea.value = "items found:"+itemcount;
if (itemcount) {
// Loop through all items, looking for any kind of image
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
// We need to represent the image as a file,
var blob = items[i].getAsFile();
// and use a URL or webkitURL (whichever is available to the browser)
// to create a temporary URL to the object
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
// The URL can then be used as the source of an image
createImage(source);
}
}
} else {
console.log("no items found. checking input");
// This is a cheap trick to make sure we read the data
// AFTER it has been inserted.
setTimeout(checkInput, 1);
}
// If we can't handle clipboard data directly (Firefox),
// we need to read what was pasted from the contenteditable element
} else {
console.log("checking input");
// This is a cheap trick to make sure we read the data
// AFTER it has been inserted.
setTimeout(checkInput, 1);
}
}
/* Parse the input in the paste catcher element */
function checkInput() {
console.log("check input");
// Store the pasted content in a variable
var child = pasteCatcher.childNodes[0];
// Clear the inner html to make sure we're always
// getting the latest inserted content
//pasteCatcher.innerHTML = "";
//console.log( "clearing catcher");
console.log(child);
if (child) {
// If the user pastes an image, the src attribute
// will represent the image as a base64 encoded string.
if (child.tagName === "IMG") {
createImage(child.src);
reader = new FileReader();
reader.readAsDataURL(child.src);
reader.loadend = function(e) {
console.log(e.target.result);
}
}
}
}
/* Creates a new image from a given source */
function createImage(source) {
var pastedImage = new Image();
pastedImage.onload = function(e) {
//pasteArea.text = pastedImage.src;
console.log(1);
console.log(e);
loadImage.src = e.target.src;
console.log(loadImage.src);
}
pastedImage.src = source;
}
<textarea id="pasteArea" placeholder="Paste Image Here"></textarea>
<img id="loadImage" />
I'm testing this in Safari on Mac.
Since the blobURI is generated automatically by the browser, you can use this, which will download the produced image as a new Blob:
const toDataURL = url => fetch(url)
.then(response => response.blob())
.then(blob => new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(blob)
}))
And then on your function createImage(source) { you can call it:
toDataURL(source)
.then(dataUrl => {
console.log('RESULT:', dataUrl)
})
This answer is complimentary to #BrunoLM's answer for when you don't have ES6 or you want to read in a different image type.
ES6:
const toDataURL = url => fetch(url)
.then(response => response.blob())
.then(blob => new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(blob)
}))
Not ES6 (seems to work the same):
const toDataURL = function(url) {
return fetch(url).then(function(response) {
return response.blob();
}).then(function (blob) {
var type = blob.type;
var size = blob.size;
return new Promise(function(resolve, reject) {
const reader = new FileReader();
reader.onerror = reject;
reader.readAsDataURL(blob);
reader.onloadend = function() {
return resolve(reader.result);
}
}
)}
)}
Based on my understanding of ES6 (ES6 to not ES6):
var a = url => fetch(url)
var a = function(url) { return fetch(url) }
var a = function(parameter) { return statement }
var b = (parameter, parameter) => { fetch(param, param) }
var b = function(foo1, foo2) => { return fetch(param, param) }
var c = url = () => resolve(reader.result)
var c = url = function() { return resolve() }
Making a call:
toDataURL(url).then(function(dataUrl) {
console.log("RESULT:" + dataUrl);
});
Note:
The value returned by the above method is of type "image/tiff" when run in Safari on OSX. If you want to specify another type, such as PNG, there more info on that here.

Using XLSX in Angular2 with IE 11

I wanted to share this as it took me a few hours to sort out details by going over the various posts.
The Task:
Using XLSX as part of my Angular2 project to import xls, xlsx, or csv type files to generate reports.
The Problem:
IE does not support the readAsBinaryString and produces an error where other web browsers do not generate errors
Solution:
Manually create prototype function for readAsBinaryString if one does not exist.
The Code:
Add One of the following functions to the component that is trying to read the file and use "readAsBinaryString". I suggest #2 but both seem to work.
Option 1:
IECheck(): void {
if (FileReader.prototype.readAsBinaryString === undefined) {
FileReader.prototype.readAsBinaryString = function (fileData) {
let binary = '';
const pt = this;
const reader = new FileReader();
reader.onload = function (e) {
const bytes = new Uint8Array(reader.result);
const length = bytes.byteLength;
for (let i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
const f = {target: {result: binary}};
pt.onload(f);
}
reader.readAsArrayBuffer(fileData);
}
}
}
Option 2:
IECheck(): void {
if (FileReader.prototype.readAsBinaryString === undefined) {
FileReader.prototype.readAsBinaryString = function (fileData) {
const pt = this;
const reader = new FileReader();
reader.onload = function (e) {
const blobURL = URL.createObjectURL(fileData);
const xhr = new XMLHttpRequest;
xhr.open('get', blobURL);
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.onload = function () {
const g = {target: {result: xhr.response}};
pt.onload(g)
}
xhr.send();
}
reader.readAsArrayBuffer(fileData);
}
}
}
In the constructor or OnInit(If using lifecycle hooks) call the IECheck function
this.IECheck();
Result:
XLXS will upload documents in IE
Let me know your thoughts on this, Happy codding!

URL encoding "data:image/jpg; base64" image

How can I encode the data:image/jpeg;base64 data url to be transmitted correctly through an AJAX POST. I have the following code xhr.open('POST', 'http://url-sent-to/image/' + saveImage + '&imageid=' + imageid.value, true); that is doing so now.
However, the URL http://url-sent-to/image/data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD…RRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAH/2Q==&imageid=testimagedata does not look like it will be correct, especially since it has = in it.
$(function () {
var fileInput = document.getElementById("file")
, renderButton = $("#renderButton")
, imgly = new ImglyKit({
container: "#container",
ratio: 1 / 1
});
// As soon as the user selects a file...
fileInput.addEventListener("change", function (event) {
var file;
var fileToBlob = event.target.files[0];
var blob = new Blob([fileToBlob], {"type":fileToBlob.type});
// do stuff with blob
console.log(blob);
// Find the selected file
if(event.target.files) {
file = event.target.files[0];
} else {
file = event.target.value;
}
// Use FileReader to turn the selected
// file into a data url. ImglyKit needs
// a data url or an image
var reader = new FileReader();
reader.onload = (function(file) {
return function (e) {
data = e.target.result;
// Run ImglyKit with the selected file
try {
imgly.run(data);
} catch (e) {
if(e.name == "NoSupportError") {
alert("Your browser does not support canvas.");
} else if(e.name == "InvalidError") {
alert("The given file is not an image");
}
}
};
})(file);
reader.readAsDataURL(file);
});
// As soon as the user clicks the render button...
// Listen for "Render final image" click
renderButton.click(function (event) {
var dataUrl;
imgly.renderToDataURL("image/jpeg", { size: "1200" }, function (err, dataUrl) {
// `dataUrl` now contains a resized rendered image with
// a width of 300 pixels while keeping the ratio
//Convert DataURL to Blob to send over Ajax
function dataURItoBlob(dataUrl) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataUrl.split(',')[1]);
// separate out the mime component
var mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
//var bb = new BlobBuilder();
//bb.append(ab);
//return bb.getBlob(mimeString);
}
var blob = dataURItoBlob(dataUrl);
var fd = new FormData(document.forms[0]);
var xhr = new XMLHttpRequest();
var saveImage = dataUrl;
//console.log(saveImage);
fd.append("myFile", blob);
xhr.open('POST', 'http://url-sent-to/image/' + saveImage + '&imageid=' + imageid.value, true);
xhr.send(fd);
I have a fiddle setup for an example of what I'm doing. Essentially, the user will select an image, enter a description, and hit render. When you check the Javascript console, you'll see a Blob is created, and the POST message at the bottom: http://jsfiddle.net/mattography/Lgduvce1/2/
You're looking for encodeURI(), which will do exactly what you're looking for.
Note that you're missing a ? to start your querystring.
Also note that making URLs that long is a bad idea; you should send a POST request instead.

Convert URL to File or Blob for FileReader.readAsDataURL

Reference: FileReader.readAsDataURL
Considering the following example:
function previewFile(file) {
var reader = new FileReader();
reader.onloadend = function () {
console.log(reader.result);
}
reader.readAsDataURL(file);
}
It states:
instanceOfFileReader.readAsDataURL(blob);
blob: The Blob or File from which to read.
How can a local file URL like: 'file:///C:/path-to/root.png' be
passed to the readAsDataURL()
Is FileReader() available in a Firefox Addon?
To convert a URL to a Blob for FileReader.readAsDataURL() do this:
var request = new XMLHttpRequest();
request.open('GET', MY_URL, true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
console.log('DataURL:', e.target.result);
};
};
request.send();
Expanding on Felix Turner s response, here is how I would use this approach with the fetch API.
async function createFile(){
let response = await fetch('http://127.0.0.1:8080/test.jpg');
let data = await response.blob();
let metadata = {
type: 'image/jpeg'
};
let file = new File([data], "test.jpg", metadata);
// ... do something with the file or return it
}
createFile();
The suggested edit queue is full for #tibor-udvari's excellent fetch answer, so I'll post my suggested edits as a new answer.
This function gets the content type from the header if returned, otherwise falls back on a settable default type.
async function getFileFromUrl(url, name, defaultType = 'image/jpeg'){
const response = await fetch(url);
const data = await response.blob();
return new File([data], name, {
type: data.type || defaultType,
});
}
// `await` can only be used in an async body, but showing it here for simplicity.
const file = await getFileFromUrl('https://example.com/image.jpg', 'example.jpg');
Try this I learned this from #nmaier when I was mucking around with converting to ico:
Well i dont really understand what array buffer is but it does what we need:
function previewFile(file) {
var reader = new FileReader();
reader.onloadend = function () {
console.log(reader.result); //this is an ArrayBuffer
}
reader.readAsArrayBuffer(file);
}
notice how i just changed your readAsDataURL to readAsArrayBuffer.
Here is the example #nmaier gave me:
https://stackoverflow.com/a/24253997/1828637
it has a fiddle
if you want to take this and make a file out of it i would think you would use file-output-stream in the onloadend
This information is outdated as of now, but cannot be deleted.
You can create File instances just by specifying a path when your code is chrome-privileged:
new File("/path/to/file");
File is a sub-class of Blob, so all File instances are also valid Blobs.
Please note that this requires a platform path, and not a file URL.
Yes, FileReader is available to addons.
File and FileReader are available in all windows. If you want to use them in a non-window scope (like bootstrap.js or a code module), you may use nsIDOMFile/nsIDOMFileReader.
Here is my code using async awaits and promises
const getBlobFromUrl = (myImageUrl) => {
return new Promise((resolve, reject) => {
let request = new XMLHttpRequest();
request.open('GET', myImageUrl, true);
request.responseType = 'blob';
request.onload = () => {
resolve(request.response);
};
request.onerror = reject;
request.send();
})
}
const getDataFromBlob = (myBlob) => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(myBlob);
})
}
const convertUrlToImageData = async (myImageUrl) => {
try {
let myBlob = await getBlobFromUrl(myImageUrl);
console.log(myBlob)
let myImageData = await getDataFromBlob(myBlob);
console.log(myImageData)
return myImageData;
} catch (err) {
console.log(err);
return null;
}
}
export default convertUrlToImageData;
I know this is an expansion off of #tibor-udvari's answer, but for a nicer copy and paste.
async function createFile(url, type){
if (typeof window === 'undefined') return // make sure we are in the browser
const response = await fetch(url)
const data = await response.blob()
const metadata = {
type: type || 'video/quicktime'
}
return new File([data], url, metadata)
}
I ended up wanting something similar to this but without having to pass the type for the file or the filename, so I made my own example based on #Felix Turner's example. I used the content-disposition header for the filename first in case the file is coming back from an API endpoint, but use the last part of the URL path if that header doesn't exist.
function getFilenameFromContentDisposition(res) {
let filename = null;
const disposition = res.headers.get("content-disposition");
if (disposition?.includes("attachment")) {
const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
const matches = filenameRegex.exec(disposition);
if (matches?.[1]) {
filename = matches[1].replace(/['"]/g, "");
// Sometimes the filename comes in a URI encoded format so decode it
filename = decodeURIComponent(filename);
// Sometimes the filename starts with UTF-8, remove that
filename = filename.replace(/^UTF-8/i, "").trim();
}
}
return filename;
}
async function getFileFromLink(url) {
const fileRes = await fetch(url);
const blob = await fileRes.blob();
let fileName = getFilenameFromContentDisposition(fileRes);
if (!fileName) {
fileName = url.split("/").pop();
}
const file = new File([blob], fileName, {
type: blob.type,
});
return file;
}
If you wanted to make this better, I'd use the content-disposition package on npm for the parsing as the formatting of it can get strange. I'd also probably use the mime package for ensuring that the filename from the URL has a proper file extension based on the returned content-type
Here's a simplest way to get blob or file object with vanila.js and promise
const fileURL_to_blob = (file_url) => {
return new Promise((resolve, reject) => {
let request = new XMLHttpRequest();
request.open('GET', file_url, true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
//console.log('DataURL:', e.target.result);
resolve(e.target.result);
};
};
request.onerror=function(e){
reject(e);
}
request.send();
});
}

Categories

Resources