Convert buffer to file [FileCollection:meteor/ostrio:files] - javascript

when i get the image from the input
i have to convert it to a buffer to make some operations with the image, so as a result a i have a buffer instead of file.
im using FileCollection in meteor to store the image in mongo collection
uploadIt(e) {
e.preventDefault();
var reader = new FileReader();
var buffer;
var file = e.currentTarget.files[0];
if (e.currentTarget.files && e.currentTarget.files[0]) {
reader.onload = function(e){
buffer = new Uint8Array(reader.result);
// some operations over the buffer
};
reader.readAsArrayBuffer(file);
if (file) {
let uploadInstance = CourseFilesCollection.insert({
file: buffer,
..
..
})
}
}
but when i insert it got this error
message: "[FilesCollection] [insert] Have you forget to pass a File itself?
the code originally was
if (file) {
let uploadInstance = CourseFilesCollection.insert({
file: file,
..
..
})
}
but since i had to perfom operations over the the image i need to someway conver the buffer to file
any ideas how to solve this ?

Short answer
use the file constructor to turn bits back to a file container:
file: new File([buffer], file.name, file)
you could try using blob also with wider browser support... but if you want to use the latest tech, then:
async uploadIt (evt) {
evt.preventDefault()
const file = evt.currentTarget.files[0]
if (!file) return
const buffer = new Uint8Array(await file.arrayBuffer())
// some operations over the buffer
const uploadInstance = CourseFilesCollection.insert({
file: new File([buffer], file.name, file)
})
}

Related

How would I convert an image to base64 in reactJS

I have this function where I call a function and have a local file as the parameter to convert it to base64.
export const fileToBase64 = (filename, filepath) => {
return new Promise(resolve => {
var file = new File([filename], filepath);
var reader = new FileReader();
// Read file content on file loaded event
reader.onload = function(event) {
resolve(event.target.result);
};
// Convert data to base64
reader.readAsDataURL(file);
});
}
Importing the function
fileToBase64("shield.png", "./form").then(result => {
console.log(result);
console.log("here");
});
gives me an output as
data:application/octet-stream;base64,c2hpZWxkLnBuZw==
here
I want base64 information, but noticing the file the application/octet-stream is wrong? I entered an image so shouldn't it be
data:image/pgn;base64,c2hpZWxkLnBuZw==
https://medium.com/#simmibadhan/converting-file-to-base64-on-javascript-client-side-b2dfdfed75f6
try this I think this should helpfull
let buff = new Buffer(result, 'base64');
let text = buff.toString('ascii');
console.log(text)

How can i read data from blob url?

I have to read the data as an array of characters or even better as an base64 string from a blob url,
for later processing.
The blobUrl that i have to read for example is
blob:https://localhost:44399/a4775972-6cc8-41a3-af64-1180d9941ab0
Actually when following the link, the file is previewed in my browser.
While trying to read the file
var blobUrl = document.getElementById("test").value;
var reader = new FileReader();
reader.readAsDataURL(blobUrl);
reader.onloadend = function ()
{
base64data = reader.result;
console.log(base64data);
}
I get the error
Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.
What am i doing wrong here?
readAsDataURL does not actually accept url as input?
How can i fix that?
As spec says, readAsDataURL accept Blob only (which is File inheritor) as a param.
So you need to use original blob file reference (if you have it) or convert URL into file instance.
To convert image URL into the file itself, you can do the following.
async function convertToFile(url){
let response = await fetch(url);
let blob = await response.blob();
return new File([blob], 'put_the_name.jpg', {
type: 'image/jpeg'
});
}
// usage
async function main() {
const url = document.getElementById("test").value; // get file URL somehow
const file = await convertToFile(url); // usage of function above
const reader = new FileReader();
reader.readAsDataURL(file);
...
}
Or if you have an input in your markup for uploading files (which is popular use case), you can get file reference directly.
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
if (file) {
reader.readAsDataURL(file);
}

Proper way to read a file using FileReader() to generate an md5 hash string from image files?

I'm currently doing this (see snippet below) to get an md5 hash string for the image files I'm uploading (I'm using the hash as fileNames):
NOTE: I'm using the md5 package to generate the hash (it's loaded into the snippet).
There are 4 available methods on FileReader() to read the files. They all seem to produce good results.
readAsText(file)
readAsBinaryString(file);
readAsArrayBuffer(file);
readAsDataURL(file);
Which is should I be using in this case and why? Can you also explain the difference between them?
function onFileSelect(e) {
const file = e.target.files[0];
const reader1 = new FileReader();
const reader2 = new FileReader();
const reader3 = new FileReader();
const reader4 = new FileReader();
reader1.onload = (event) => {
const fileContent = event.target.result;
console.log('Hash from "readAsText()": ');
console.log(md5(fileContent));
}
reader2.onload = (event) => {
const fileContent = event.target.result;
console.log('Hash from "readAsBinaryString()": ');
console.log(md5(fileContent));
}
reader3.onload = (event) => {
const fileContent = event.target.result;
console.log('Hash from "readAsArrayBuffer()": ');
console.log(md5(fileContent));
}
reader4.onload = (event) => {
const fileContent = event.target.result;
console.log('Hash from "readAsDataURL()": ');
console.log(md5(fileContent));
}
reader1.readAsText(file);
reader2.readAsBinaryString(file);
reader3.readAsArrayBuffer(file);
reader4.readAsDataURL(file);
}
.myDiv {
margin-bottom: 10px;
}
<script src="https://cdn.jsdelivr.net/npm/js-md5#0.7.3/src/md5.min.js"></script>
<div class="myDiv">Pick an image file to see the 4 hash results on console.log()</div>
<input type='file' onChange="onFileSelect(event)" accept='.jpg,.jpeg,.png,.gif' />
Use readAsArrayBuffer.
readAsBinaryString() and readAsDataURL() will make your computer do a lot more work than what needs to be done:
read the blob as binary stream
convert to UTF-16 / base64 String (remember strings are not mutable in js, any operation you do on it will actually create a copy in memory)
[ pass to your lib ]
convert to binary string
process the data
Also, it seems your library doesn't handle data URLs and fails on UTF-16 strings.
readAsText() by default will try to interpret you binary data as an UTF-8 text sequence, which is pretty bad for binary data like raster image:
// generate some binary data
document.createElement('canvas').toBlob(blob => {
const utf8_reader = new FileReader();
const bin_reader = new FileReader();
let done = 0;
utf8_reader.onload = bin_reader.onload = e => {
if(++done===2) {
console.log('same results: ', bin_reader.result === utf8_reader.result);
console.log("utf8\n", utf8_reader.result);
console.log("utf16\n", bin_reader.result);
}
}
utf8_reader.readAsText(blob);
bin_reader.readAsBinaryString(blob);
});
readAsArrayBuffer on the other hand will just allocate the binary data as is in memory. Simple I/O, no processing.
To manipulate this data, we can use TypedArrays views over this binary data, which being only views, won't create any overhead either.
And if you look at the library you are using, they will anyway pass your input to such an Uint8Array to further process it. However beware they apparently need you to pass an Uint8Array view of this ArrayBuffer instead of the nude ArrayBuffer directly.

How to encode base 64 to .kml file?

I convert kml file to base 64. Now I want to encode base 64 to become kml file again? is this possible? I convert kml file like this..
$scope.myFunction = function () {
var files = document.getElementById('myFile').files;
if (files.length > 0) {
getBase64(files[0]);
}
}
function getBase64(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
console.log(reader.result);
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
}
how can I store kml file to database?
It surely is possible, you just have to decode the base64 and turn the result into a file again.
function base64ToFile(base64){
content=atob(base64);
var file = new Blob([content], {type: 'kml'});
//You can now asign the file to a link to download, send it with ajax, etc..
a.href = URL.createObjectURL(file);
}
Bear in mind, that you cant write a file directly onto disk from javascript, because that would be a security issue, you need t

Read huge files in browser using FileReader (web api)

I'm trying to read the first byte of the selected file.
But when I select a large file (>100Mb) I get an error: "NotReadableError".
See the code below. Is "array buffer" really a buffer or it just loads the whole stuff into the memory and I MUST use file#slice?
function readFile(file) {
var reader = new FileReader();
reader.onload = function() {
var buffer = reader.result;
var view = new Int8Array(buffer);
try {
view.forEach(function(v, index, array) {
console.log(v);
alert("ok - " + v);
throw "BreakException";
})
} catch (e) {
if (e!=="BreakException") throw e;
}
}
reader.onerror = function() {
alert("error");
console.log(reader.error);
}
reader.readAsArrayBuffer(file);
}
var fileField = document.getElementById("file");
fileField.onchange = function(e) {
var file = e.target.files[0];
readFile(file);
}
<form>
<input id="file" type="file"/>
</form>
An ArrayBuffer is really a buffer, an in-memory buffer. That's how buffers work. Your code tries to load the whole file into memory. To access specific ranges of a file without loading the whole into memory, you must use Blob.slice (Files implement all the methods of Blobs) as you suspected.

Categories

Resources