Meteor: large base64 files preventing download - javascript

I am trying to download files that were uploaded from MongoDB using gridfs. The download works for small files but does not work for files bigger than 1MB, no error message no thing happens. Is there a way around the file size issue?
Event:
Template.form.events({
"click #chunk": function() {
let doc = Images.findOne({_id:"TK8mmSg9CvjxwSxE5"});
let chunk = filenamechunks.find({files_id:new Meteor.Collection.ObjectID(doc.copies.images.key)}).fetch();
if (chunk.length > 0) {
let chunksize = 0xffff;
let len = chunk[0].data.length;
let strings = [];
for (var y = 0; y < chunk.length; y++) {
for (var i = 0; i * chunksize < len; i++){
strings.push(String.fromCharCode.apply(null, chunk[y].data.subarray(i * chunksize, (i + 1) * chunksize)));
};
};
let content = btoa(strings.join(''));
let link = window.document.createElement("a");
link.setAttribute("href", "data:"+doc.copies.type+";base64," + content);
link.setAttribute("download", "test."+doc.copies.name.split(".")[1]);
link.click();
};
}
});
HTML:
<template name="form">
<button id="chunk">click</button>
</template>
Publish:
Meteor.publish("chunks", function(id){
return filenamechunks.find({files_id:new Meteor.Collection.ObjectID(id)});
});
Subscribe:
Template.form.onCreated(function() {
this.subscribe("chunks","56fbaa2c850d6b341a0c3344");
});
Packages:

Related

How to get video resolution on browser/javascript?

I need to validate video resolution, if it's above 1280x720, I need to block it before user uploads it. How to do this on browser or javascript?
Can use mp4box npm library.
import MP4Box from 'mp4box'
let reader = new FileReader()
const mp4boxfile = MP4Box.createFile();
function _base64ToArrayBuffer(base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
reader.onload = function() {
mp4boxfile.onReady = function (info) {
console.log('Video info: ', info); // resolution info is available on info.videoTracks[0].video.width and .height
}
const arrayBuffer = _base64ToArrayBuffer(reader.result.slice(22))
arrayBuffer.fileStart = 0;
mp4boxfile.appendBuffer(arrayBuffer);
};
reader.readAsDataURL(videoFile); // videoFile comes from onChange event of input file element
Video codec info detail as well as video duration also available on info object.

Convert Image URI to File or Blob

I am able to get the image URI using Ionic Image Picker plugin:
this.imagePicker.getPictures(options).then((results) => {
for (var i = 0; i < results.length; i++) {
//below logs: 'Image URI: file:///Users/josh.0/Library/Developer/CoreSimulator/Devices/CC0FFBD2-EADF-4489-8F22-7948E0EFD261/data/Containers/Data/Application/2BC3C571-61B7-4EFF-A4D1-4D1F99F04EBC/tmp/cdv_photo_013.jpg'
console.log('Image URI: ' + results[i]);
}
}, (err) => { });
I need to get this image as a File, so I can upload it. I've tried doing the following, but it doesn't work:
this.imagePicker.getPictures(options).then((results) => {
for (var i = 0; i < results.length; i++) {
console.log('Image URI: ' + results[i]);
let base64Image = "data:image/jpeg;base64," + results[i];
fetch(base64Image)
.then(res => res.blob())
.then(blob => {
//Doesnt fire
console.log("Got blob")
const file = new File([blob], "image.png")
})
}
}, (err) => { });
How do I convert an image URI to file?
Ionic really needs to improve their documentation. The documentation on the plugin in the docs is absolutely pathetic. Took me hours to figure this out on my own. Anyway, here it is:
getImage() {
const options = {
maximumImagesCount: 1,
width: 800,
height: 800,
quality: 100,
outputType: 1 //Set output type to 1 to get base64img
};
this.imagePicker.getPictures(options).then((results) => {
var files: File[] = [];
for (var i = 0; i < results.length; i++) {
console.log('Image URI: ' + results[i]);
let blob = this.getBlob(results[i], ".jpg")
const file = new File([blob], "image.jpg")
//Do something with file like upload
}
}, (err) => { });
}
private getBlob(b64Data:string, contentType:string, sliceSize:number= 512) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
let byteCharacters = atob(b64Data);
let byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
let slice = byteCharacters.slice(offset, offset + sliceSize);
let byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
let blob = new Blob(byteArrays, {type: contentType});
return blob;
}
You need to get the file from the directory with AJAX. I use AngularJS and below is what I used to get the Blob. You can pretty much convert this to whatever JS framework/library you're using.
AngularJS method:
$http.get(file_uri, {'responseType':'blob'}).then(successMethod, failMethod);

Failed to execute 'postMessage' on 'Worker': FormData object could not be cloned

I am using web workers for uploading larger file by creating chunks using slice but when I am sending the file in the form of formData object, it is throwing this error.when I do this in reactjs it is throwing following error
react-dom.development.js:518 Warning: React does not recognize the offClick prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase offclick instead. If you accidentally passed it from a parent component, remove it from the DOM element.
here is my code, where I am passing formData object to worker using postMessage, please help me to resolve this
<!DOCTYPE html>
<html>
<head>
<title>Using FileReaderSync Example</title>
<script id="worker1" type="javascript/worker">
var file = [], p = true;
function upload(blobOrFile) {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'url', true);//add url to upload
xhr.onload = function(e) {
};
xhr.send(blobOrFile);
}
function process() {
for (var j = 0; j <file.length; j++) {
var blob = file[j];
const BYTES_PER_CHUNK = 1024 * 1024;
// 1MB chunk sizes.
const SIZE = blob.size;
var start = 0;
var end = BYTES_PER_CHUNK;
while (start < SIZE) {
if ('mozSlice' in blob) {
var chunk = blob.mozSlice(start, end);
} else {
var chunk = blob.slice(start, end);
}
upload(chunk);
start = end;
end = start + BYTES_PER_CHUNK;
}
p = ( j = file.length - 1) ? true : false;
self.postMessage(blob.name + " Uploaded Succesfully");
}
}
self.addEventListener('message', function(e) {
for (var j = 0; j < e.data.files.length; j++)
file.push(e.data.files[j]);
if (p) {
process()
}
})
</script>
<script>
var blob = new Blob([document.querySelector('#worker1').textContent]);
var worker = new Worker(window.URL.createObjectURL(blob));
worker.onmessage = function(e) {
alert(e.data);
};
worker.onerror =werror;
function werror(e) {
console.log('ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message);
}
function handleFileSelect(evt) {
console.log("coming");
evt.stopPropagation();
evt.preventDefault();
let files = new FormData();
files.append('file', event.target.files );
//var files = evt.target.files;
// FileList object.
worker.postMessage({
'files' : files
});
//Sending File list to worker
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ', f.size, ' bytes, last modified: ', f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a', '</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
// Explicitly show this is a copy.
}
function getd(){
document.getElementById('files').addEventListener('change', handleFileSelect, false);
}
window.addEventListener("load", getd, false);
</script>
</head>
<body>
<input type="file" id="files" name="files[]"/>
<output id="list"></output>
</body>
</html>
You do not use the worker API properly. You should have a look to this https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
your worker file should looks like:
self.onmessage = function(e) {
// Do all the work here the postMessage the result
self.postMessage(result)
}
You "main" file is good :)
const worker = new Worker('yourWorkerFilePath')
worker.onmessage() = function(resultFormWorker) {
// treate the result here
}
worker.postMessage(file)

How do I delete multiple files at once in Drive API for Javascript?

function deleteFiles(fileId,supportsTeamDrives) {
var date = new Date();
date.setDate(date.getDate() - 180);
var n = date.toISOString().split('.')[0] ;
var test = false;
gapi.client.drive.files.list({
pageSize: x,
q: "starred = "+test+" and viewedByMeTime < '"+n+"'",
orderBy: 'quotaBytesUsed desc',
fields: "nextPageToken, files(id, name, viewedByMeTime, mimeType, quotaBytesUsed)",
}
)
.then(function(response) {
var files = response.result.files;
if (files && files.length > 0) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var file_id = file.id,
)');
}}
var request = gapi.client.drive.files.delete({
supportsTeamDrives: 'false',
fileId: file_id ,
}); }
request.execute(function(resp) { });
}
I want this function to list out the fileIDs, as as each fileID is put out, they get deleted. How do I combine list file and delete file functions together for this to work?
Currently I separated them into two functions, but the variable fileID only saves the last fileID outputted, thus, the delete function would only delete one file, the last file listed. I want it to list and output every file to a varable and as its listed it gets deleted. What can I change or add in my goal to accomplish this?
You can alter your code to delete the file in your loop:
function deleteFiles(fileId, supportsTeamDrives) {
var date = new Date();
date.setDate(date.getDate() - 180);
var n = date.toISOString().split('.')[0];
var test = false;
gapi.client.drive.files.list({
pageSize: x,
q: "starred = " + test + " and viewedByMeTime < '" + n + "'",
orderBy: 'quotaBytesUsed desc',
fields: "nextPageToken, files(id, name, viewedByMeTime, mimeType, quotaBytesUsed)",
}
)
.then(function(response) {
var files = response.result.files;
if (files && files.length > 0) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var file_id = file.id;
deleteFile(file_id);
}
}
});
}
// method used to delete the files
function deleteFile(file_id) {
var request = gapi.client.drive.files.delete({
supportsTeamDrives: 'false',
fileId: file_id,
});
request.execute(function(resp) {});
}

Allow only images in file upload form element in directory HTML5

HTML Code
<input type="file" accept="image/*" multiple webkitdirectory mozdirectory msdirectory odirectory directory id="fileURL"/>
Javascript Code:
var files,
file,
extension,
sum,
input = document.getElementById("fileURL"),
output = document.getElementById("fileOutput"),
holder = document.getElementById("fileHolder")
sizeShow = document.getElementById("filesSize");
input.addEventListener("change", function (e) {
files = e.target.files;
output.innerHTML = "";
sum = 0;
for (var i = 0, len = files.length; i < len; i++) {
file = files[i];
extension = file.name.split(".").pop();
if(extension=="jpg"||extension=="png"){
var size = Math.floor(file.size/1024 * 100)/100;
sum = size+sum;
output.innerHTML += "<li class='type-" + extension + "'>"+file.webkitRelativePath + file.name + " (" + size + "KB)</li>";
}else{
file.remove();
}
}
if(sum<1024*1024){
sizeShow.innerHTML = Math.floor(sum/1024*100)/100 + " MB";
}else if(sum>1024*1024){
sizeShow.innerHTML = Math.floor(sum/1024*1024*100)/100 + " GB";
}
}, false);
How do i get just the image in the file upload? accept="image/*" doesn't work for directory.
This does work but the statement file.remove() doesn't work at all.
I guess the input:file is read-only.
How do i solve this?
You can set input.files to a FileList (obtained from e.g. drag and drop), but you cannot create/modify a FileList. So you cannot modify the files of an input to e.g. only contain images.
What you can do, though, is uploading manually (through ajax), and only send files that have a type starting with "image/". See http://jsfiddle.net/WM6Sh/1/.
$("form").on("submit", function(e) {
e.preventDefault();
var files = $(this).find("input").prop("files");
var images = $.grep(files, function(file) {
return file.type.indexOf("image/") === 0; // filter out images
});
var xhr = new XMLHttpRequest();
xhr.open("POST", "/", true);
$(xhr).on("readystatechange", function(e) {
if(xhr.readyState === 4) {
console.log("Done");
}
});
var data = new FormData();
$.each(images, function(i) {
data.append(i, this); // append each image file to the data to be sent
});
console.log(
"Sending %d images instead of all %d files...",
images.length,
files.length
);
xhr.send(data);
});

Categories