Reputation: 8519
For learning purposes, I want to use the html input tag to select a jpeg image, retrieve the File Object, load it with fileReader and use the retrieved image string (base64) to create a new blob/file.
the service can upload the original file retrieved from the input just fine. However using my newFile the file get's corrupted and the file size somehow is larger.
I figure I'm doing something wrong with the blob constructor?
I'm using angular2 in typescript
<input type="file" (change)="onFileChanged($event)">
onFileChanged(event){
if (event.target.files && event.target.files[0]) {
let file = event.target.files[0];
let newFile;
let fr = new FileReader();
fr.onload = (event:any)=>{
let base64 = event.target.result
let img = base64.split(',')[1]
let blob = new Blob([window.atob(img)],{type:'image/jpeg'})
newFile = this.blobToFile(blob,'test')
}
fr.readAsDataURL(file)
console.log(file)
console.log(newFile)
this.service.upload(newFile).subscribe()
}
}
blobToFile(blob: Blob, fileName: string): File {
let b: any = blob;
b.lastModified = moment.now();
b.lastModifiedDate = new Date();
b.name = fileName;
b.webkitRelativePath="";
return <File>blob
}
EDIT------------ After finding out that fileReader is asynchronous, i've adjusted it a little bit and indeed the problem is with the blob constructor. loggin the both the target.result of original file and new one revealed that the base64 as been transmuted. Any ideas why?
if (event.target.files && event.target.files[0]) {
let file = event.target.files[0];
let base64: string = null;
if (/^image\//.test(file.type)) {
let reader = new FileReader();
reader.onload = (e: any) => {
console.log(e.target)
base64 = e.target.result
let img = base64.split(',')[1];
let blob = new Blob([img], { type: 'image/jpeg' })
console.log(blob);
let fr = new FileReader()
fr.onload = (event: any) => {
console.log(event.target)
}
fr.readAsDataURL(blob)
}
reader.readAsDataURL(file);
}
Upvotes: 3
Views: 8476
Reputation: 1760
I am suspecting your code:
onFileChanged(event){
if (event.target.files && event.target.files[0]) {
let file = event.target.files[0];
let newFile;
let fr = new FileReader();
fr.onload = (event:any)=>{
let base64 = event.target.result
let img = base64.split(',')[1]
let blob = new Blob([window.atob(img)],{type:'image/jpeg'})
newFile = this.blobToFile(blob,'test')
}
fr.readAsDataURL(file)
console.log(file)
console.log(newFile)
this.service.upload(newFile).subscribe()
}
}
onFileChanged(event) and (event:any), these two 'event' mean different objects. event in onFileChanged is the event object of onFileChanged. event in fr.onload is the event object of FileReader.onload. Don't you think it is confusing and might cause cross reference?
Upvotes: 0
Reputation: 6824
Modify your function like this. Because FileReader
is asynchronous, to process the result, you need to do it inside the onload
callback, but here, you are uploading the file outside of onload
which at that point, is undefined
or whatever initial value it contains.
onFileChanged(event){
if (event.target.files && event.target.files[0]) {
let file = event.target.files[0];
let newFile;
let fr = new FileReader();
fr.onload = (event:any)=>{
let base64 = event.target.result
let img = base64.split(',')[1]
let blob = new Blob([window.atob(img)],{type:'image/jpeg'})
newFile = this.blobToFile(blob,'test')
this.service.upload(newFile).subscribe()
}
fr.readAsDataURL(file)
console.log(file)
console.log(newFile) // Either prints undefined or whatever initial value it contains
}
}
Upvotes: 3