Send an image in the data uri format using ngFlow - javascript

I am using an input to load an image, then converting it in the data uri format to pass it into the ngImgCrop directive to crop that image.
So far I have all of this working, but I am struggling trying to upload the cropped image which is in the data uri format using ngFlow.
I have been tried several ways with no success, has anyone been able to do this?
I am afraid I am missing something, I tried using the .addFile() method and passing in the image in the data uri format but it does not work this way.

I finally found a solution, creating a Blob and pushing it into Flow's files array worked!
This StackOverflow answer also helped, as I had to convert the image in the data uri format to binary to create the Blob (the function dataURItoBlob() did it for me).
Here's the code that did it:
function uploadImage($flow) {
if ($flow) {
// 'vm.img.cropped' is the image in data uri format to upload
var blob = dataURItoBlob(vm.img.cropped);
blob.name = 'file.png';
var file = new Flow.FlowFile($flow, blob);
$flow.files.push(file)
$flow.upload();
}
}
function dataURItoBlob(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type: mimeString});
};

Related

Taking an image and converting it into BLOB for MySQL

I am trying to make a JavaScript that would take an image file and covert it into BLOB (by converting the file into Base64 first and then into BLOB), my project doesn't have a support for toBlob() so I have found different convering steps and put them together and they work to a point where I have to pass the BLOB from the function where its made out for the Mysql part of code that takes care of communicating with the database. (I have that fully working). Now I only need to find a way how to connect them through a variable that saves the results of the imageforQuery function.
My code so far is this:
let base64String = "";
function imageforQuery(imageid) {
//takes file and converts to Base64
var file = document.getElementById(imageid).files[0];
var reader = new FileReader();
console.log("next");
imgFileFrontBlob = "";
reader.onload = function () {
base64String = reader.result.replace("data:", "")
.replace(/^.+,/, "");
// console.log(base64String);
base64String = 'data:image/jpeg;base64,'+ base64String;
console.log(base64String);
//converts Base64 into BLOB
var binary = atob(base64String.split(',')[1]);
console.log(binary);
var array = [];
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
var imgFileFrontBlob = new Blob([new Uint8Array(array)], {type: 'image/png'});
console.log(imgFileFrontBlob);
return imgFileFrontBlob
}
reader.readAsDataURL(file);
};
by experimenting with console.log() at different stages and return I have found out that I can't pass the converted BLOB result out, as the function imageforQuery() only returns what is after reader.readAsDataURL(file); and I don't know of a way of getting that result out.
––––––––––––––ADDITIONAL PROBLEMS I HAVE ENCOUNTERED––––––––––––––
okay so thanks to Emiel Zuurbier (Thank you!) I have managed to rewrite my code with the help of his solution. However as much as it helped one part of the problem, it didn't help with the JavaScript Blob object as we found out it is not the exact same thing as SQL BLOB.
Now the problem is that upon trying to send the Blob object in a SQL query, this resulted in just sending pure text "[Blob object]".
But I am using JavaScript successfully to pull the data from a BLOB field from my database and convert it into Base64 images from that data that was stored in the BLOB in a different part of my application. The code for that is below:
var converterEngine = function (input) {
// fn BLOB => Binary => Base64 ?
var uInt8Array = new Uint8Array(input),
i = uInt8Array.length;
var biStr = []; //new Array(I);
while (i--) { biStr[i] = String.fromCharCode(uInt8Array[i]); }
var base64 = window.btoa(biStr.join(''));
return base64;
};
What I need to do is just reverse this and in theory, it should get me the same data that I receive from the database.
My reversal code is below:
// this is the inside bit of code from the first problem that is solved and the
// typeOfData variable is parsed into the function in imageforQuery() as a second input
// variable (in other words its not to be of concern)
reader.onload = function () {
let base64String = reader.result.replace("data:", "").replace(/^.+,/, "");
base64String = "data:" + typeOfData + ";base64," + base64String;
var binary = atob(base64String.split(",")[1]);
// console.log(binary);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
var ourArray = new Uint8Array(array);
resolve(ourArray);
};
However, as I mentioned the data that comes out (ourArray) isn't actually identical to the original file from the BLOB in the database so my code doesn't function correctly and I don't know why. Any ideas where I've made a mistake?
Base64 is simply ascii text. So MySQL's datatype BLOB or TEXT would work. That is, after converting to Base64, don't worry about "convert to blob"; it is not necessary.
That is, you can probably replace the code from //converts ... through return ... by simply
return base64String;
You can wrap the FileReader instance and calls inside of a Promise. Return the Promise immediately. In the reader.onload function call resolve() to exit the Promise with a value.
function imageforQuery(imageid) {
return new Promise(resolve => {
var file = document.getElementById(imageid).files[0];
var reader = new FileReader();
reader.onload = function () {
let base64String = reader.result.replace("data:", "").replace(/^.+,/, "");
base64String = "data:image/jpeg;base64," + base64String;
var binary = atob(base64String.split(",")[1]);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
var imgFileFrontBlob = new Blob([new Uint8Array(array)], {
type: "image/png",
});
resolve(imgFileFrontBlob);
};
reader.readAsDataURL(file);
});
}
This results in being able to use your function like here below. imageforQuery is called, returns a Promise. When the promise is finished (meaning resolve is called) the function in the then method will run.
imageforQuery(imageId).then(imgFileFrontBlob => {
// Use your blob here.
saveToDB(imgFileFrontBlob); // Example of how you would use it.
});
Or use it with async / await.
(async () => {
function imageforQuery(imageid) {
...
}
// Here we can wait for imageforQuery to finish and save the variable.
const imgFileFrontBlob = await imageforQuery(imageId);
saveToDB(imgFileFrontBlob); // Example of how you would use it.
})()

Blazor Server-Side JS Invoking

Hi I'm trying to move the bytes of my video which is in c# to javascript to make the bytes into URL.createObjectURL on Blazor server-side
I moved the bytes using Js Invoke
.cs
if (!string.IsNullOrEmpty(item.PathFile))
{
//Byte Video
byte[] result = GetFile(item.PathFile);
if (result != null)
{
var url = await Js.InvokeAsync<string>("videoUrl", result);
data.ImageString = url;
}
}
.js
function videoUrl(value) {
var byteCharacters = atob(value);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
//Byte Array -> Blob
var file = new Blob([byteArray], { type: 'data:video/mp4;base64' });
//Blob -> Object URL
var fileURL = URL.createObjectURL(file);
return fileURL;
}
My problem is, I tried this script for a video with a size of 3 Mb it runs fine, but when I try for a 133Mb video I get an error:
Error: System.ArgumentException: The JSON value of length 139569235 is too large and not supported.
I've tried to fix it, but it still fails, it makes me a little frustrated
So is there a solution for my error ? or what should I do?
I thank you for any suggestions or feedback
So, reading on the AspNetDocs github, there is a startup option that can change the max message size, but I think it only applies to calls from JS to .Net (https://github.com/dotnet/AspNetCore.Docs/issues/21208). Worth a check though.
services.AddServerSideBlazor()
.AddHubOptions(options => options.MaximumReceiveMessageSize = 32000);
Personally though, I would do as Mister Magoo said in the comment and either use an API or chunk the data and reassemble at the other end.

Base64 to Image File Convertion in JS

I am working on a project where I have to upload an image as form data along with other text fields. I have my file in Base64 string at first, then I convert it into a file before uploading it to the server.
const data = await fetch(base64String);
const blob = await data.blob();
const file = await new File([blob], 'avatar', { type: 'image/png' });
I logged the base64String in the client side before uploading it to the server. Then I upload file to the server as a File. Before saving it to MongoDB when I log it as a base64 string again in the server side, I see my string is not the same as before. I feel like while converting the base64 to file in the client side I am doing something wrong. Help me out please.
I have figured out my problem. When I take image file input from my computer I get a base64 string like below -
dataimage/jpegbase64/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA...
But, when I convert it back into a file it expects a string like below -
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA....
So, basically, I had to trim the string accordingly to match the expected format and wrote a base64 to file conversion function following this answer.
Here is my function to convert a base64 string to an image file
export function getFileFromBase64(string64:string, fileName:string) {
const trimmedString = string64.replace('dataimage/jpegbase64', '');
const imageContent = atob(trimmedString);
const buffer = new ArrayBuffer(imageContent.length);
const view = new Uint8Array(buffer);
for (let n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
const type = 'image/jpeg';
const blob = new Blob([buffer], { type });
return new File([blob], fileName, { lastModified: new Date().getTime(), type });
}

How to decode and download base64 string(excel data) and download the file?

I'm getting excel data encoded as base64 string from backend. I want to decode this data and download the excel file in the browser. I'm using vuejs as my frontend. Also if I were to show this data in table format on the frontend, how can I go about doing that? Thanks in advance for the response.
This is what I have tried-
public downloadfile() {
var data = window.atob("string");
this.save("file", data, ".xls");
}
public save(name: any, data: any, type: any) {
var bytes = new Array(data.length);
console.log("here", bytes);
for (var i = 0; i < data.length; i++) {
bytes[i] = data.charCodeAt(i);
}
data = new Uint8Array(bytes);
var blob = new Blob([data], { type: type });
console.log(blob);
let objectURL = window.URL.createObjectURL(blob);
let anchor = document.createElement("a");
anchor.href = objectURL;
anchor.download = name;
anchor.click();
URL.revokeObjectURL(objectURL);
}
I have a run button on clicking that downloadfile runs. and a file.txt gets downloaded. What am I doing wrong here? If I rename the file format to xls, that file shows correct data.
You need a browser Javascript library that understands excel format. I have used sheetjs with good success in the past.

Illegal Constructor error: convert Base64 to Blob fails on cordova

I want to convert my Base64 image to a blob in my cordova app project using AngularJS but i keep getting Illegal constructor error. I have tried a lot of the solutions given online but none seems to be working. Any help is appreciated.
var imageElement = angular.element(document.querySelector('#profileImg'));
var imageURI = dataURIToBlobURI(imageElement.attr('src'));
function dataURIToBlobURI(dataURI) {
// 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(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.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);
}
var bb = new Blob([ab], {type: 'image/png'});
return bb;
}
I keep getting an error over here new Blob([ab], {type: 'image/png'}) and dont seem to knw how to make it work. Only happens when the app is in Android or iOS not when viewed in Chrome.
I have tried the following but all to no avail.
var bb = new Blob(ab);
var bb = new Blob([ab]);
var bb = new Blob(dataURI);
Thanks
Kingsley! Possible, device where you could reproduce the error doesn't support Blob actually. Actually you could use two ways:
Firstly, check
polyfill or smth similar to fix your problem. It will allow you to use Blob as a constructor.
Secondly, you could use BlobBuilder except of Blob. Small exmaple below,
var bb = new BlobBuilder();
bb.append('blob content');
var blob = bb.getBlob('text/plain');
I used this to solve my problem. Just incase anyone runs into this problem. All solutions didnt work for me on my device. Just follow instructions and add the javascript file and you shud be fine. https://github.com/blueimp/JavaScript-Canvas-to-Blob
var b64Data = 'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
'OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofE' +
'ovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5PKsAAA7',
imageUrl = 'data:image/gif;base64,' + b64Data,
blob = window.dataURLtoBlob && window.dataURLtoBlob(imageUrl);

Categories

Resources