I am trying to crop image using the angular library "ngx-image-cropper". Thereafter cropping, I am getting an image in the base64 format so I want to convert that image to file format. I am using the following code to convert base64 string to BLOB and then BLOB to file format.
fileChangeEvent(event: any): void {
this.imageChangedEvent = event;
}
imageCropped(event: ImageCroppedEvent) {
this.croppedImage = event.base64;
var result = this.b64toBlob(this.croppedImage);
var file = new File([result], 'uploaded_file.jpg', {type: 'image/jpeg', lastModified: Date.now()});
}
b64toBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: 'image/jpeg' });
}
But on BLOB to file conversion I am getting error "ERROR TypeError: File is not a constructor". What should I do to resolve this issue?
Thanks in advance.
I was facing the same problem and I have fixed it after removing the File type from the component variable.
public imageFile: File = null;
The solution works for me:
public imageFile = null;
Related
I am trying to convert base64 data to file using javascript on asp.net, but i am getting( 0x800a01bd - JavaScript runtime error: Object doesn't support this action) error on final stage while converting blob to file at final stage.
Here is my code:
function dataBaseURLtoFile(str) {
// extract content type and base64 payload from original string
var pos = str.indexOf(';base64,');
var type = str.substring(5, pos);
var b64 = str.substr(pos + 8);
// decode base64
var imageContent = atob(b64);
// create an ArrayBuffer and a view (as unsigned 8-bit)
var buffer = new ArrayBuffer(imageContent.length);
var view = new Uint8Array(buffer);
// fill the view, using the decoded base64
for (var n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
// convert ArrayBuffer to Blob
var blob = new Blob([buffer], { type: type });
//convert blob to file
var file = new File([blob], "name", { type: "image/jpeg", });
return file;
}
I try to check your code and found that issue is on line below.
var file = new File([blob], "name", { type: "image/jpeg", });
IE and Edge browser does not supports the File() constructor.
File.File() constructor
For IE and Edge browser you need to use any alternative way.
You can try to refer thread below may give you some helpful information about alternative ways.
Is there an alternative for File() constructor for Safari and IE?
Im looking to resize an image before it is uploaded to a server, at the moment i am using ng2-imageupload like this:
<input id="media" class="inputfile" type="file" name="media" image-upload
(imageSelected)="selected($event)"
[resizeOptions]="resizeOptions" (change)="onChange($event)">
export class WpMediaFormComponent {
file: File;
resizeOptions: ResizeOptions = {
resizeMaxHeight: 768,
resizeMaxWidth: 438
};
selected(imageResult: ImageResult) {
console.log(imageResult);
this.dataBlob = this.dataURItoBlob(imageResult.resized.dataURL);
let blob = this.dataURItoBlob(imageResult.resized.dataURL);
}
This then returns an object, like this:
dataURL:"data:image/jpeg;base64, DATA URI HERE"
type:"image/jpeg;"
I can then convert this object to a blob using this function:
dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = decodeURI(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
Before doing this I was uploading the image to the server using this code:
onChange(event: EventTarget) {
let eventObj: MSInputMethodContext = <MSInputMethodContext> event;
let target: HTMLInputElement = <HTMLInputElement> eventObj.target;
let files: FileList = target.files;
this.file = files[0];
console.log(this.file);
//this.update.emit(this.file);
}
Does anyone have idea how I can feed the blob returned from dataURItoBlob method into the file upload onChange event?
Im a little lost here.
So I figured it out with the help of #Brother Woodrow, and this thread:
How to convert Blob to File in JavaScript
Here is my updated code, not the only thing I had to change was the selected method:
selected(imageResult: ImageResult) {
// create a blob
let blob: Blob = this.dataURItoBlob(imageResult.resized.dataURL);
// get the filename
let fileName: string = imageResult.file.name;
// create a file
this.file = new File([blob], fileName);
console.log(this.file);
// event emitter send to container then to http post
this.update.emit(this.file);
}
I can now upload 3MB and they are pushed to the server around 150kB in seconds which is great for the user especially as this app will mostly be used by mobile devices.
You'll need to convert the Data URI to a Blob, then send that back to your server. This might be helpful: Convert Data URI to File then append to FormData
Once you have the blob, it should be easy enough to use FormData and the Angular HTTP class to upload it to your server for further processing.
let formData = new FormData();
formData.append(blob);
this.http.post('your/api/url', fd).subscribe((response) => console.log(reponse);
I want to convert Base64String extracted from file(ex: "AAAAA....~") to a javascript file object.
The javascript file object what I mean is like this code:
HTML:
<input type="file" id="selectFile" >
JS:
$('#selectFile').on('change', function(e) {
var file = e.target.files[0];
console.log(file)
}
'file' variable is a javascript file object. So I want to convert a base64 string to the javascript file object like that.
I just want to get file object by decoding base64 string (encoded by other app from a file) without html file input form.
Thank you.
Way 1: only works for dataURL, not for other types of url.
function dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {type:mime});
}
//Usage example:
var file = dataURLtoFile('data:text/plain;base64,aGVsbG8gd29ybGQ=','hello.txt');
console.log(file);
Way 2: works for any type of url, (http url, dataURL, blobURL, etc...)
//return a promise that resolves with a File instance
function urltoFile(url, filename, mimeType){
return (fetch(url)
.then(function(res){return res.arrayBuffer();})
.then(function(buf){return new File([buf], filename,{type:mimeType});})
);
}
//Usage example:
urltoFile('data:text/plain;base64,aGVsbG8gd29ybGQ=', 'hello.txt','text/plain')
.then(function(file){ console.log(file);});
const url = 'data:image/png;base6....';
fetch(url)
.then(res => res.blob())
.then(blob => {
const file = new File([blob], "File name",{ type: "image/png" })
})
Base64 String -> Blob -> File.
This is the latest async/await pattern solution.
export async function dataUrlToFile(dataUrl: string, fileName: string): Promise<File> {
const res: Response = await fetch(dataUrl);
const blob: Blob = await res.blob();
return new File([blob], fileName, { type: 'image/png' });
}
const file = new File([
new Blob(["decoded_base64_String"])
], "output_file_name");
You could use a lib like this to decode and encode base64 to arrayBuffer.
I had a very similar requirement (importing a base64 encoded image from an external xml import file. After using xml2json-light library to convert to a json object, I was able to leverage insight from cuixiping's answer above to convert the incoming b64 encoded image to a file object.
const imgName = incomingImage['FileName'];
const imgExt = imgName.split('.').pop();
let mimeType = 'image/png';
if (imgExt.toLowerCase() !== 'png') {
mimeType = 'image/jpeg';
}
const imgB64 = incomingImage['_#ttribute'];
const bstr = atob(imgB64);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
const file = new File([u8arr], imgName, {type: mimeType});
My incoming json object had two properties after conversion by xml2json-light: FileName and _#ttribute (which was b64 image data contained in the body of the incoming element.) I needed to generate the mime-type based on the incoming FileName extension. Once I had all the pieces extracted/referenced from the json object, it was a simple task (using cuixiping's supplied code reference) to generate the new File object which was completely compatible with my existing classes that expected a file object generated from the browser element.
Hope this helps connects the dots for others.
Here is the Typescript version of accepted answer above by #cuixiping, now using Buffer instead of atob()
I saw deprecation warnings using atob() from TypeScript, although it isn't fully deprecated. Only one overload is. However, I converted mine to use the deprecation warning suggestion of Buffer. It seems more clean since it requires no extra loop to convert each character.
/***
* Converts a dataUrl base64 image string into a File byte array
* dataUrl example:
* data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIsAAACLCAYAAABRGWr/AAAAAXNSR0IA...etc
*/
dataUrlToFile(dataUrl: string, filename: string): File | undefined {
const arr = dataUrl.split(',');
if (arr.length < 2) { return undefined; }
const mimeArr = arr[0].match(/:(.*?);/);
if (!mimeArr || mimeArr.length < 2) { return undefined; }
const mime = mimeArr[1];
const buff = Buffer.from(arr[1], 'base64');
return new File([buff], filename, {type:mime});
}
at the top of the file you'll need an import to make the typings happy.
import { Buffer } from 'buffer';
No special npm packages are needed.
Heads up,
JAVASCRIPT
<script>
function readMtlAtClient(){
mtlFileContent = '';
var mtlFile = document.getElementById('mtlFileInput').files[0];
var readerMTL = new FileReader();
// Closure to capture the file information.
readerMTL.onload = (function(reader) {
return function() {
mtlFileContent = reader.result;
mtlFileContent = mtlFileContent.replace('data:;base64,', '');
mtlFileContent = window.atob(mtlFileContent);
};
})(readerMTL);
readerMTL.readAsDataURL(mtlFile);
}
</script>
HTML
<input class="FullWidth" type="file" name="mtlFileInput" value="" id="mtlFileInput"
onchange="readMtlAtClient()" accept=".mtl"/>
Then mtlFileContent has your text as a decoded string !
Complete Version for Typescript
async uploadImage(b64img: string) {
var file = await this.urltoFile(b64img,'name.png',this.base64MimeType(b64img));
}
//return a promise that resolves with a File instance
urltoFile(url, filename, mimeType){
return (fetch(url)
.then(function(res){return res.arrayBuffer();})
.then(function(buf){return new File([buf], filename,{type:mimeType});})
);
}
//return mime Type of bs64
base64MimeType(encoded) {
var result = null;
if (typeof encoded !== 'string') {
return result;
}
var mime = encoded.match(/data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+).*,.*/);
if (mime && mime.length) {
result = mime[1];
}
return result;
}
Thats Work for me Converting base64 Image to File
I have an image represented as data URL. I want this image to be converted into a blob.
I use the following method for this purpose:
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
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 arrayBuffer = new ArrayBuffer(byteString.length);
var _ia = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteString.length; i++) {
_ia[i] = byteString.charCodeAt(i);
}
var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });
return blob;
}
This function is working but as I found here: Blob support the blob sometimes need the webkit prefix to work. I know that for URL I could use the fallback with
var _URL = URL || webkitURL;
How do I have to include the webkit prefix version as a fallback for older browsers in my function? Do I have to use BlobBuilder() instead on Blob()?
Best way to feature detect support for Blob is try and catch
function supportsBlob() {
try {
return !!new Blob();
} catch (e) {
return false;
}
}
Based on the question Open PDF in new browser full window, it looks like I can use JavaScript to open a new window with a PDF file with the following code:
window.open('MyPDF.pdf', '_blank');
I'd like to do so on a return trip from the server by adding a byte array instead of the file name to use as the URL location in window.open
I'm currently returning PDF files like this:
Response.Clear();
Response.ContentType = "application/pdf";
Response.BinaryWrite(pdfByteArray);
Response.Flush();
Is there a way to open a new window with a PDF byte array in javascript.
Something like this:
var script = "window.open('" + pdfByteArray + "', '_blank');";
ScriptManager.RegisterClientScriptBlock(Parent.Page, typeof(Page), "pdf", script, true);
It looks like window.open will take a Data URI as the location parameter.
So you can open it like this from the question: Opening PDF String in new window with javascript:
window.open("data:application/pdf;base64, " + base64EncodedPDF);
Here's an runnable example in plunker, and sample pdf file that's already base64 encoded.
Then on the server, you can convert the byte array to base64 encoding like this:
string fileName = #"C:\TEMP\TEST.pdf";
byte[] pdfByteArray = System.IO.File.ReadAllBytes(fileName);
string base64EncodedPDF = System.Convert.ToBase64String(pdfByteArray);
NOTE: This seems difficult to implement in IE because the URL length is prohibitively small for sending an entire PDF.
Note: I have verified this in the latest version of IE, and other browsers like Mozilla and Chrome and this works for me. Hope it works for others as well.
if (data == "" || data == undefined) {
alert("Falied to open PDF.");
} else { //For IE using atob convert base64 encoded data to byte array
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], {
type: 'application/pdf'
});
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else { // Directly use base 64 encoded data for rest browsers (not IE)
var base64EncodedPDF = data;
var dataURI = "data:application/pdf;base64," + base64EncodedPDF;
window.open(dataURI, '_blank');
}
}
Adding to #Dinesh's answer to handle Not allowed to navigate top frame to data URL error in Chrome and Edge
if (data == "" || data == undefined) {
// Log Error: PDF data not available
} else {
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var file = new Blob([byteArray], { type: 'application/pdf;base64' });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
// For IE
window.navigator.msSaveOrOpenBlob(file, 'mypdf.pdf');
} else {
// For non-IE
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
}