Load files into a blob to zip and upload - javascript

I want to add all files to a blob and zip then upload using plupload.
I've googled for days looking for answer and have not been able to figure it out.
uploader.bind('FilesAdded', function(up, files) {
plupload.each(files,function(file) {
source = file.getSource();
relative_path = source.relativePath
var fileCount = up.files.length;
var ids = $.map(up.files, function (item) { return item.id; });
alert(source);
arrayFiles[index] = source;
if (index + 1 == files_remaining){
output = pako.gzip(arrayFiles , {to : "Uint8Array"});
myBlob = new Blob(arrayFiles);
uploader.addFile(myBlob);
index = 0;
}
index++;

Related

How to filter by file path in Google apps script

I am trying to have the following script filter by file path. Ideally this should only show results from the folder marked 'GUEST' in my drive. Right now it shows those and anything else with the shared folder ID of this root (I do not want to use the GUEST folder ID because I will later use this to filter other users accessing my drive).
My google drive file path is as follows Root/GUEST
CODE UPDATED WITH ANSWER FROM COMMENTS:
var folderId = "MyID"; // <--- Your shared folder ID
function doGet() {
var t = HtmlService.createTemplateFromFile('index');
t.data = getFileList();
return t.evaluate() .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);;
}
function getparams(e) {
return zipping(typeof(e.fileId) == "string" ? [e.fileId] : e.fileId);
}
function getFileList() {
var folderlist = (function(folder, folderSt, results) {
var ar = [];
var folders = folder.getFoldersByName("GUEST");
while (folders.hasNext()) ar.push(folders.next());
folderSt += folder.getId() + "#_aabbccddee_#";
var array_folderSt = folderSt.split("#_aabbccddee_#");
array_folderSt.pop()
results.push(array_folderSt);
ar.length == 0 && (folderSt = "");
for (var i in ar) arguments.callee(ar[i], folderSt, results);
return results;
})(DriveApp.getFoldersByName("GUEST").next(), "", []);
var localTimeZone = Session.getScriptTimeZone();
var filelist = [];
var temp = {};
for (var i in folderlist) {
var folderid = folderlist[i][folderlist[i].length - 1];
var folder = DriveApp.getFoldersByName("GUEST");
var files = folder.next().getFiles();
while (files.hasNext()) {
var file = files.next();
temp = {
folder_tree: function(folderlist, i) {
if (i > 0) {
return "/" + [DriveApp.getFolderById(folderlist[i][j]).getName() for (j in folderlist[i])
if (j > 0)].join("/") + "/";
} else {
return "/";
}
}(folderlist, i),
file_id: file.getId(),
file_name: file.getName(),
file_size: file.getBlob().getBytes().length,
file_created: Utilities.formatDate(file.getDateCreated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
file_updated: Utilities.formatDate(file.getLastUpdated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
};
filelist.push(temp);
temp = {}
}
}
var sortedlist = filelist.sort(function(e1, e2) {
return (e1.folder_tree > e2.folder_tree ? 1 : -1) });
return sortedlist;
}
function zipping(fileId) {
var blobs = [];
var mimeInf = [];
fileId.forEach(function(e) {
try {
var file = DriveApp.getFileById(e);
var mime = file.getMimeType();
var name = file.getName();
} catch (e) {
return e
}
Logger.log(mime)
var blob;
if (mime.indexOf('google-apps') > 0) {
mimeInf =
mime == "application/vnd.google-apps.spreadsheet" ? ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", name + ".xlsx"] : mime == "application/vnd.google-apps.document" ? ["application/vnd.openxmlformats-officedocument.wordprocessingml.document", name + ".docx"] : mime == "application/vnd.google-apps.presentation" ? ["application/vnd.openxmlformats-officedocument.presentationml.presentation", name + ".pptx"] : ["application/pdf", name + ".pdf"];
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + e + "/export?mimeType=" + mimeInf[0], {
method: "GET",
headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
muteHttpExceptions: true
}).getBlob().setName(mimeInf[1]);
} else {
blob = UrlFetchApp.fetch("https://www.googleapis.com/drive/v3/files/" + e + "?alt=media", {
method: "GET",
headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
muteHttpExceptions: true
}).getBlob().setName(name);
}
blobs.push(blob);
});
var zip = Utilities.zip(blobs, Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyyMMdd_HHmmss") + '.zip');
var bytedat = DriveApp.createFile(zip).getBlob().getBytes();
return Utilities.base64Encode(bytedat);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script>
function postLogin(event) {
var form = document.getElementById("myForm");
form.submit();
event.preventDefault();
}
</script>
<a href="" onClick="postLogin(event);" >Click!</a>
<form id="myForm" action="MYEXECLINK" target="my_iframe"></form>
<iframe id="my_iframe"name="my_iframe" style= "width: 500px; height: 50%;" frameBorder="0" style="overflow:hidden"></iframe>
I tried to use an if statement at line 61, but it could not pull the variables for some reason (I think I'm not setting up my variables correctly):
if (filelist(folder_tree == "/GUEST/"){
return sortedlist;}
else
{return null}
Does anyone know how to make this script filter by folder_tree? Hopefully by comparing it to a var (like user=guest)?
To clarify, here is the current result:
And this is the expected output:
Thanks for any help, I'll post updates as I work on it to clarify.
You want to retrieve a file list under the specific folder.
Subfolders in the specific folder are not required to be retrieved.
You want to achieve this using Google Apps Script.
I could understand like above. If my understanding is correct, how about this modification? I think that your updated script works. But I thought that your script might be able to be modified more simple. So how about the following modification?
Modification point:
In this modification, getFileList() was modified.
In your script, at first, the folder tree is retrieved. Then, the files in all folders are retrieved. But in your situation, the folder tree is not required to be retrieved. By this, your script can be modified more simple.
At first, "FileIterator" are retrieved with DriveApp.getFoldersByName("GUEST").next().getFiles(). Then, the values are retrieved from "FileIterator".
Modified script:
function getFileList() {
var folderName = "GUEST";
var files = DriveApp.getFoldersByName(folderName).next().getFiles();
var localTimeZone = Session.getScriptTimeZone();
var filelist = [];
while (files.hasNext()) {
var file = files.next();
var temp = {
file_id: file.getId(),
file_name: file.getName(),
file_size: file.getBlob().getBytes().length,
file_created: Utilities.formatDate(file.getDateCreated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
file_updated: Utilities.formatDate(file.getLastUpdated(), localTimeZone, "yyyy/MM/dd HH:mm:ss"),
};
filelist.push(temp);
}
return filelist;
}
References:
getFoldersByName(name)
getFiles()
Class FileIterator

How to add an attachement to an email (not stored in file disk)

I want to open outlook with an attachement (zip) using Javascript.
It's working fine if the file in in some directory in the computer client.
this.sendEmail = function (zip) {
try {
var theApp = new ActiveXObject("Outlook.Application");
var objNS = theApp.GetNameSpace('MAPI');
var theMailItem = theApp.CreateItem(0); // value 0 = MailItem
theMailItem.to = ('test#gmail.com');
theMailItem.Subject = ('test');
theMailItem.Body = ('test');
theMailItem.Attachments.Add(zip);
theMailItem.display();
}
catch (err) {
alert(err.message);
}
};
But What I want to do is to add the file that I have alredy in memory
this.SenddZip = function (docDescription, fileName) {
var zip = new JSZip();
for (var i = 0; i < docDescription.length; i++) {
var doc = docDescription[i];
zip.file(doc.core_documenttitle + doc.core_fileextension, doc.fileBase64, { base64: true });
}
Utils.sendEmail(zip);
// Generate the zip file asynchronously
zip.generateAsync({ type: "blob" })
.then(function (content) {
// Force down of the Zip file
var name = "documents";
if (fileName) {
name = fileName;
}
// location.href = "data:application/zip;base64," + content;
saveAs(content, name + ".zip");
Utils.sendEmail(xxxxxxxx);
});
};
If their is no solution for this :
Is their a way to download the document without the confirmation dialog ?
saveAs ask always for confirmation before to store the file.
Thank you

How to read files from folder

Found this article which showing how to distinguish file upload from directory How to handle dropped folders but they not explain how I can handle the directory upload. Having difficulties to find any example. Anyone know how to get File instance of each file in directory?
Copied from that article:
<div id=”dropzone”></div>
var dropzone = document.getElementById('dropzone');
dropzone.ondrop = function(e) {
var length = e.dataTransfer.items.length;
for (var i = 0; i < length; i++) {
var entry = e.dataTransfer.items[i].webkitGetAsEntry();
if (entry.isFile) {
... // do whatever you want
} else if (entry.isDirectory) {
... // do whatever you want
}
}
};
Use DirectoryReader directoryEntry.createReader() , readEntries() for folders or , FileEntry file() for single or multiple file drops.
html
<div id="dropzone"
ondragenter="event.stopPropagation(); event.preventDefault();"
ondragover="event.stopPropagation(); event.preventDefault();"
ondrop="event.stopPropagation(); event.preventDefault(); handleDrop(event);">
Drop files
</div>
javascript
function handleFiles(file) {
console.log(file);
// do stuff with `File` having `type` including `image`
if (/image/.test(file.type)) {
var img = new Image;
img.onload = function() {
var figure = document.createElement("figure");
var figcaption = document.createElement("figcaption");
figcaption.innerHTML = file.name;
figure.appendChild(figcaption);
figure.appendChild(this);
document.body.appendChild(figure);
URL.revokeObjectURL(url);
}
var url = URL.createObjectURL(file);
img.src = url;
} else {
console.log(file.type)
}
}
function handleDrop(event) {
var dt = event.dataTransfer;
var files = dt.files;
var length = event.dataTransfer.items.length;
for (var i = 0; i < length; i++) {
var entry = dt.items[i].webkitGetAsEntry();
if (entry.isFile) {
// do whatever you want
console.log("isFile", entry.isFile);
entry.file(handleFiles);
} else if (entry.isDirectory) {
// do whatever you want
console.log("isDirectory", entry.isDirectory);
var reader = entry.createReader();
reader.readEntries(function(entries) {
entries.forEach(function(dir, key) {
dir.file(handleFiles);
})
})
}
}
}
plnkr http://plnkr.co/edit/eGAnbA?p=preview
After you drag some file from your disk. This event.dataTransfer.file is your fileList object.
Your could create a formData then
Add files from fileList to formData one by one.
In the end you could submit formData to server with Ajax

JSZip Memory Issue

I am experiencing high memory consumption on my Node.js app, when loading ~100MB zip files one after the other it is keeping them in memory as a "NodeBufferReader". The library I am using is called JSZip and is found here: https://stuk.github.io/jszip/
If I access the same zip file twice then it doesn't increase memory usage but for every 'extra' .zip file I access the memory increases by approx the size of the .zip file. The files I am accessing are all around 100MB or larger so as you can imagine this has the potential to get rather large, rather quickly.
The Node.js application is a websocket server that reads files from within .zip files and returns them back to the requestor as base64 data. The function in question is here:
function handleFileRequest(args, connection_id) {
var zipIndex = 0,
pathLen = 0,
zip_file = "",
zip_subdir = "";
try {
if (args.custom.file.indexOf(".zip") > -1) {
// We have a .zip directory!
zipIndex = args.custom.file.indexOf(".zip") + 4;
pathLen = args.custom.file.length;
zip_file = args.custom.file.substring(0, zipIndex);
zip_subdir = args.custom.file.substring(zipIndex + 1, pathLen);
fs.readFile(zip_file, function (err, data) {
if (!err) {
zipObj.load(data);
if (zipObj.file(zip_subdir)) {
var binary = zipObj.file(zip_subdir).asBinary();
var base64data = btoa(binary);
var extension = args.custom.file.split('.').pop();
var b64Header = "data:" + MIME[extension] + ";base64,";
var tag2 = args.custom.tag2 || "unset";
var tag3 = args.custom.tag3 || "unset";
var rargs = {
action: "getFile",
tag: args.tag,
dialogName: connections[connection_id].dialogName,
custom: {
file: b64Header + base64data,
tag2: tag2,
tag3: tag3
}
};
connections[connection_id].sendUTF(JSON.stringify(rargs));
rargs = null;
binary = null;
base64data = null;
} else {
serverLog(connection_id, "Requested file doesn't exist");
}
} else {
serverLog(connection_id, "There was an error retrieving the zip file data");
}
});
} else {
// File isn't a .zip
}
} catch (e) {
serverLog(connection_id, e);
}
}
Any help would be much appreciated in getting rid of this problem - Thanks!
Working Code Example
function handleFileRequest(args, connection_id) {
var zipIndex = 0,
pathLen = 0,
f = "",
d = "";
try {
if (args.custom.file.indexOf(".zip") > -1) {
// We have a .zip directory!
zipIndex = args.custom.file.indexOf(".zip") + 4;
pathLen = args.custom.file.length;
f = args.custom.file.substring(0, zipIndex);
d = args.custom.file.substring(zipIndex + 1, pathLen);
fs.readFile(f, function (err, data) {
var rargs = null,
binary = null,
base64data = null,
zipObj = null;
if (!err) {
zipObj = new JSZip();
zipObj.load(data);
if (zipObj.file(d)) {
binary = zipObj.file(d).asBinary();
base64data = btoa(binary);
var extension = args.custom.file.split('.').pop();
var b64Header = "data:" + MIME[extension] + ";base64,";
var tag2 = args.custom.tag2 || "unset";
var tag3 = args.custom.tag3 || "unset";
rargs = {
action: "getFile",
tag: args.tag,
dialogName: connections[connection_id].dialogName,
custom: {
file: b64Header + base64data,
tag2: tag2,
tag3: tag3
}
};
connections[connection_id].sendUTF(JSON.stringify(rargs));
} else {
serverLog(connection_id, "Requested file doesn't exist");
}
} else {
serverLog(connection_id, "There was an error retrieving the zip file data");
}
rargs = null;
binary = null;
base64data = null;
zipObj = null;
});
} else {
// Non-Zip file
}
} catch (e) {
serverLog(connection_id, e);
}
}
If you use the same JSZip instance to load each and every file, you will keep everything in memory : the load method doesn't replace the existing content.
Try using a new JSZip instance each time :
var zipObj = new JSZip();
zipObj.load(data);
// or var zipObj = new JSZip(data);

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