Download whole Folder (google drive api) - javascript

Hey guy's I have an google drive app.
Where I can download upload and many more things.
The problem is that I need to be able to download the "folder" as well.
So the scenario is:
Folder1
-FolderA
--fileA1
--fileA2
--FolderAA
---fileAA1
---FileAA2
---FolderAAA
----FileAAA1
-FolderB
-FolderC
--FileC1
If I click on download folder 1 I want it to download all the things u see
If I click on download folderC he only download Folderc (or zip) with filec1 in it.
The files are easy to download because they have webContentLink
I already read:
Download folder with Google Drive API

You will need to do a Files.list which will return a list of each of the files.
{
"kind": "drive#fileList",
"nextPageToken": string,
"incompleteSearch": boolean,
"files": [
files Resource
]
}
Loop though each of the files and download it. If you are after a way of doing it in a single request then there isn't one. You will need to download each file one by one.

Although question is already answered, I had a similar situation and wanted to share some code. The code recursively digs through folders and saves the files in the exact hierarchy.
The code is C#, but also pretty much self-explanatory. Hoping it might do some help.
private void downloadFile(DriveService MyService, File FileResource, string path)
{
if (FileResource.MimeType != "application/vnd.google-apps.folder")
{
var stream = new System.IO.MemoryStream();
MyService.Files.Get(FileResource.Id).Download(stream);
System.IO.FileStream file = new System.IO.FileStream(path + #"/" + FileResource.Title, System.IO.FileMode.Create, System.IO.FileAccess.Write);
stream.WriteTo(file);
file.Close();
}
else
{
string NewPath = Path + #"/" + FileResource.Title;
System.IO.Directory.CreateDirectory(NewPath);
var SubFolderItems = RessInFolder(MyService, FileResource.Id);
foreach (var Item in SubFolderItems)
downloadFile(Item, NewPath);
}
}
public List<File> RessInFolder(DriveService service, string folderId)
{
List<File> TList = new List<File>();
var request = service.Children.List(folderId);
do
{
var children = request.Execute();
foreach (ChildReference child in children.Items)
TList.Add(service.Files.Get(child.Id).Execute());
request.PageToken = children.NextPageToken;
} while (!String.IsNullOrEmpty(request.PageToken));
return TList;
}
Note that this code was written for API v2 and Children.List is not there in API v3. Do use files.list with ?q='parent_id'+in+parents if you use v3.

Related

Delete all files with a specific name, and * extension at Azure Blob Storage

I have a process where a client uploads a document. This document can be in the form of a PDF, JPG or PNG file only and it should be reuploaded once a year (it is an errors and omissions insurance policy).
I am saving this file in a container.
For deleting files from anywhere at the application, I have this function (Node):
deleteFromBlob = async function (account, accountKey, containerName, blobFolder, blobName) {
try {
const {
BlobServiceClient,
StorageSharedKeyCredential
} = require("#azure/storage-blob");
const sharedKeyCredential = new StorageSharedKeyCredential(account, accountKey);
const blobServiceClient = new BlobServiceClient(
`https://${account}.blob.core.windows.net`,
sharedKeyCredential
);
const containerClient = blobServiceClient.getContainerClient(containerName);
const blockBlobClient = containerClient.getBlockBlobClient(blobFolder + '/' + blobName);
const uploadblobResponse = await blockBlobClient.deleteIfExists()
return true
}
catch(e) {
return false
}
}
And this works perfect when I know the file name and extension I want to delete, like "2448.pdf":
let deleteFile = await utils.deleteFromBlob(account, accountKey, "agents", "/eopolicies/", userData.agentid.toString() + ".pdf" )
But the problem Im facing is that the function above is to delete a file I know exists; for example, if the agent ID is 2448 and he uploads "policy.pdf" I save it as "2448.pdf" for easy file identification.
The problem Im facing is if the agent uploaded a .PNG last year. a .DOC a year before, and a .PDF now. If that's the case, I want to delete 2448.* and keep only the latest version of the document.
So I tried changing my function to
let deleteFile = await utils.deleteFromBlob(account, accountKey, "agents", "/eopolicies/", userData.agentid.toString() + ".*" )
And of course it is not working...
I tried to find a solution and all I found is one to list the content of a folder, then loop it and delete the specific file I want; but that will not work for me since there are 37,000 EO policies on that folder.
Is there a way to delete files with a specific name, and whatever extension?
Thanks.
I've never tried using a wildcard on the extension side of the file name. However, I would iterate through the files in the directory and find the one that contains the specific string you are looking for. Get it's index, and delete from there.

Extract a non ZIP file to files on disk?

I got a App File which is structured like a zip file.
Now I would like to extract all of the files in the app file.
I tried to convert the app to a zip file in the code (just copy and paste as zip file), but then it's a "SFX ZIP Archive", which most of the unzipper in node.js can't read.
For example AdmZip (error message):
rejected promise not handled within 1 second: Error: Invalid CEN
header (bad signature)
var AdmZip = require('adm-zip');
var admZip2 = new AdmZip("C:\\temp\\Test\\Microsoft_System.zip");
admZip2.extractAllTo("C:\\temp\\Test\\System", true)
So now i don't know how to deal with it, because I need to extract the files with all subfolder/subfiles to a specific folder on the computer.
How would you do this?
You can download the .app file here:
https://drive.google.com/file/d/1i7v_SsRwJdykhxu_rJzRCAOmam5dAt-9/view?usp=sharing
If you open it, you should see something like this:
Thanks for your help :)
EDIT:
I'm already using JSZip for resaving the zip file as a normal ZIP Archive. But this is a extra step which costs some time.
Maybe someone knows how to extract files to a path with JSZip :)
EDIT 2:
Just for you information: It's a VS Code Extension Project
EDIT 3:
I got something which worked for me.
For my solution I did it with Workers (Because parallel)
var zip = new JSZip();
zip.loadAsync(data).then(async function (contents) {
zip.remove('SymbolReference.json');
zip.remove('[Content_Types].xml');
zip.remove('MediaIdListing.xml');
zip.remove('navigation.xml');
zip.remove('NavxManifest.xml');
zip.remove('Translations');
zip.remove('layout');
zip.remove('ProfileSymbolReferences');
zip.remove('addin');
zip.remove('logo');
//workerdata.files = Object.keys(contents.files)
//so you loop through contents.files and foreach file you get the dirname
//then check if the dir exists (create if not)
//after this you create the file with its content
//you have to rewrite some code to fit your code, because this whole code are
//from 2 files, hope it helps someone :)
Object.keys(workerData.files.slice(workerData.startIndex, workerData.endIndex)).forEach(function (filename, index) {
workerData.zip.file(filename).async('nodebuffer').then(async function (content) {
var destPath = path.join(workerData.baseAppFolderApp, filename);
var dirname = path.dirname(destPath);
// Create Directory if is doesn't exists
await createOnNotExist(dirname);
files[index] = false;
fs.writeFile(destPath, content, async function (err) {
// This is code for my logic
files[index] = true;
if (!files.includes(false)) {
parentPort.postMessage(workerData);
};
});
});
});
jsZip is A library for creating, reading and editing .zip files with JavaScript, with a lovely and simple API.
link (https://www.npmjs.com/package/jszip)
example (extraction)
var JSZip = require('JSZip');
fs.readFile(filePath, function(err, data) {
if (!err) {
var zip = new JSZip();
zip.loadAsync(data).then(function(contents) {
Object.keys(contents.files).forEach(function(filename) {
zip.file(filename).async('nodebuffer').then(function(content) {
var dest = path + filename;
fs.writeFileSync(dest, content);
});
});
});
}
});
The file is a valid zip file appended to some sort of executable.
The easiest way is to extract it calling an unzipper such as unzipada.exe - free, open-source software available here. Pre-built Windows executables available in the Files section.

NodeJs Microsoft Azure Storage SDK Download File to Stream

I just started working with the Microsoft Azure Storage SDK for NodeJS (https://github.com/Azure/azure-storage-node) and already successfully uploaded my first pdf files to the cloud storage.
However, now I started looking at the documentation, in order to download my files as a node_buffer (so I dont have to use fs.createWriteStream), however the documentation is not giving any examples of how this works. The only thing they are writing is "There are also several ways to download files. For example, getFileToStream downloads the file to a stream:", but then they only show one example, which is using the fs.createWriteStream, which I dont want to use.
I was also not able to find anything on Google that really helped me, so I was wondering if anybody has experience with doing this and could share a code sample with me?
The getFileToStream function need a writable stream as param. If you want all the data wrote to a Buffer instead of a file, you just need to create a custom writable stream.
const { Writable } = require('stream');
let bufferArray = [];
const myWriteStream = new Writable({
write(chunk, encoding, callback) {
bufferArray.push(...chunk)
callback();
}
});
myWriteStream.on('finish', function () {
// all the data is stored inside this dataBuffer
let dataBuffer = Buffer.from(bufferArray);
})
then pass myWriteStream to getFileToStream function
fileService.getFileToStream('taskshare', 'taskdirectory', 'taskfile', myWriteStream, function(error, result, response) {
if (!error) {
// file retrieved
}
});

File Upload using Selenium HtmlUnitDriver-headless webdriver

I'm trying to upload a local file (C:\sample.txt) to my server. I have tried to implement this with Chrome web driver and its working absolutely fine.
But during implementing the same with HTMLUnitDriver, i couldn't browse the file item from my local disk. I tried the below two methods as well,
1) Send keys:
WebElement inputFile = driver.findElement(By.id("file"));
System.out.println(driver.getCurrentUrl());
LocalFileDetector detector = new LocalFileDetector();
String path = "C:\\UploadSample1.txt";
File f = detector.getLocalFile(path);
inputFile.sendKeys(f.getAbsolutePath());
2) Using a Robot:
WebElement browseFile = fluentWait(By.id("browseFile"), driver);
browseFile.click();
File file = new File("C:\\UploadSample1.txt");
driver.switchTo().activeElement();
StringSelection fileNameToWrite = new StringSelection(
file.getAbsolutePath());
Toolkit.getDefaultToolkit().getSystemClipboard()
.setContents(fileNameToWrite, null);
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
I need the file item to be browsed, then only i can save it to my server. Because just sending the file path will be searching the file in server disk. Now i'm really stuck and couldn't move further.
Any help is highly appreciated. Thankyou!
If you need to browse to the file first, that isn't possible IMHO; for that you will need AutoIT (as Robot class is not recommended). So your best bet would be sending file path using sendKeys.
formInput.setValueAttribute(formValue); worked fine for me.
Code snippet:
Iterator<String> formValueIterator = formValues.keySet().iterator();
while(formValueIterator.hasNext()){
String formKey = formValueIterator.next();
String formValue = formValues.get(formKey);
HtmlInput formInput = form.getInputByName(formKey);
if (formInput != null)
if (formInput instanceof HtmlPasswordInput) {
((HtmlPasswordInput)formInput).setValueAttribute(formValue);
} else {
formInput.setValueAttribute(formValue);
}
}

how to access a file on the client's machine

I have a few clients that will be using my website, and I want each client to have their own "config" file (EX: location=1 for one computer, location=2 for another). I want to do this using a file I place on the client's machine and then when they access the website the client looks on their own machine and figures out what to load based on what's in that file. This file can be a CSV file, plain text file, or any other kind of file that it needs to be for this to work.
Looking online all I've seen is stuff with file uploader. I don't want them to have to select the file, just have the file contents load and call a javascript function when they do.
Example of file
Location=1
AnswerToQuestion=42
and another file
Location=2
AnswerToQuestion=15
and my JS function
var setAnswerToQuestion = function(answer){
locationConfig.setAnswer(answer)
}
Take a look at localstorage. It's a persistent key/value system that the browser implements to keep data for your website/webapp.
The Basic Principle:
To set a variable:
localStorage.setItem('answer_1', '42');
To get a variable:
localStorage.getItem("answer_1");
I guess if you have lots of answers you would end up with an array/object something like this:
var answers = [42, 15];
Towards a Solution:
You could store and retrieve that by using JSON.stringify
localStorage.setItem('answers', JSON.stringify(answers));
var answers = JSON.stringify(localStorage.getItem('answers'));
Be Educated
Smashing Magazine has a tutorial here
Dive into HTML5 has a tutorial here
You can't access files on local machines without using "file upload". You could store your config files on browser localstorage as:
var getConfigData = function() {
return JSON.parse(localStorage.getItem('config'));
}
var saveConfigData = function(config) {
localStorage.setItem('config', JSON.stringify(config));
}
var addDataToConfig = function(key, value) {
var config = getConfigData();
config[key] = value;
saveConfigData(config);
}
var config = {
Location: 1,
AnswerToQuestion: 42
};
// save new config
saveConfigData(config);
// add new data to config
addDataToConfig('name', 'John Doe');

Categories