I have a script that receives a gzipped blob from 3rd party API. I'm trying to un-gzip it using Utilities.ungzip() but getting an Invalid Argument error. Here's a sample code:
var liveReportResponse = UrlFetchApp.fetch(url)
var unzipped = Utilities.ungzip(liveReportResponse.getBlob()) // Fails with Invalid Argument error
An odd thing is that I can extract the content using the Drive File as intermediate storage:
var image = liveReportResponse.getBlob()
var file = {
title: 'some_file_.gzip'
};
file = Drive.Files.insert(file, image);
var file = DriveApp.getFileById(file.id)
var blob = file.getBlob()
var someBytes = Utilities.ungzip(blob) // It works
var data = someBytes.getDataAsString()
Would appreciate any help for fixing that.
Eventually, managed to fix that with:
liveReportResponse.getBlob().setContentType('application/x-gzip')
application/x-gzip seems not to be documented anywhere, but I've got it from blob.getContentType()
Related
I am accessing a list of folders from a shared drive.
In here, I am converting a few excel files into spreadsheet. My issue is to replace the old converted files with the new file. This is because every time i run the script the new converted file(with same name) keeps on multiplying in the same folder together with the old one.
Here is the code:
function ConvertFiles() {
var sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var r= 2;
for(r= 2;r < sheet.getLastRow(); r++){
// Use getValue instead of getValues
var fileId = sheet.getRange(r,1).getValue();
var folderID = sheet.getRange(r,8).getValue();
var files = DriveApp.getFileById(fileId);
var name = files.getName().split('.')[0];
var blob = files.getBlob();
var newFile = {
// Remove '_converted' from name if existing to avoid duplication of the string before adding '_converted'
// This will allow to have newly converted file "replace" the old converted file properly
title: name.replace('_converted','') + '_converted',
parents: [{
id: folderID
}]
};
var destinationFolderId = DriveApp.getFolderById(folderID);
var existingFiles = destinationFolderId.getFilesByName(newFile.title);
// GOAL #1: To replace/update the old converted file into the latest one everytime the script runs (if it has the same filename)
// Find the file with same name of the file to be converted
while(existingFiles.hasNext()) {
// ID of the file with same converted name
var oldConvertedFileWithSameNameID = existingFiles.next().getId();
// Delete before writing
Drive.Files.remove(oldConvertedFileWithSameNameID);
//DriveApp.getFileById(oldConvertedFileWithSameNameID.getId()).setTrashed(true);
}
// Create new converted file then get ID
var newFileID = Drive.Files.insert(newFile, blob, { convert: true,supportsAllDrives: true }).id;
Logger.log(newFileID);
//var sheetFileID = newFileID.getId();
//var Url = "https://drive.google.com/open?id=" + sheetFileID;
var Url = "https://drive.google.com/open?id=" + newFileID;
// Add the ID of the converted file
sheet.getRange(r,9).setValue(newFileID);
sheet.getRange(r,10).setValue(Url);
}
}
My goal is
To replace the old converted file with the new one(if they have the same name) into the shared drive folder
To get to know how can i implement the setTrashed() inside the above code
I have tried using the Drive.Files.remove(oldConvertedFileWithSameNameID); but I am getting an error message GoogleJsonResponseException: API call to drive.files.delete failed with error: File not found:("fileid"). Then i saw an question on this [https://stackoverflow.com/questions/55150681/delete-files-via-drive-api-failed-with-error-insufficient-permissions-for-this]...so i guess that method is not suitable to implemented in shared folder.
So i how can i use setTrashed() method inside the above code?
I think you need to set the supportsAllDrives parameter:
Drive.Files.remove(oldConvertedFileWithSameNameID, {supportsAllDrives: true});
References:
Files:delete | Google Drive API | Google Developers - Parameters
var sourceFolderId = "15Kux2yyL_OWoZBwnYPbJtyrlp1zQjY3T";
var folder = DriveApp.getFolderById(sourceFolderId);
var token = ScriptApp.getOAuthToken()
var imageUrl = folder.getFilesByName(uid).next().getDownloadUrl() + "&access_token=" +
ScriptApp.getOAuthToken();
var slide = Slides.Presentations.get(newTargetDocId).slides[0]
Logger.log(token)
Logger.log(imageUrl)
I have been using the above code to get an image from google drive and using batchupdate put it into google slides, however the auth token no longer allows a download, do i need to refresh it somehow?
The url goes to the correct image and the image is the correct file format but the code returns
API call to slides.presentations.batchUpdate failed with error: Invalid requests[1].createImage: The provided image is in an unsupported format. (line 243, file "Code").
I know the image is ok as i have already used it. I know the url is correct as it takes me to the image if i cut the authtoken off. The authtoken on the end no longer allows me to download the file on another browser.
New code based on comment about Drive changes
var sourceFolderId = "15Ku...............zQjY3T";
var folder = DriveApp.getFolderById(sourceFolderId);
var file = folder.getFilesByName(uid).next()
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var imageUrl = "https://drive.google.com/uc?export=download&id=" + file.getId();
But now i get an invalid argument error on file.setSharing line
var sourceFolderId = "15Ku...............zQjY3T";
var folder = DriveApp.getFolderById(sourceFolderId);
var file = folder.getFilesByName(uid).next()
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
var imageUrl = "https://drive.google.com/uc?export=download&id=" + file.getId();
General file permissions will need to be altered to allow this to run with Gsuite admin pages
I am downloading a .zip from a website. It contains one .txt file. I would like to access the data in the txt and write it to a spreadsheet. I'm open to either accessing it directly and not extracting the zip OR extracting the zip, saving the txt to a Google Drive Folder, and accessing it once it is saved.
When I use Utilities.unzip(), I can never get it to unzip the file and usually end up with an "Invalid argument" error. In the code below, the last section before else contains the unzip command. It successfully saves the file to the correct Google Folder but then I can't extract it.
function myFunction() {
// define where to gather data from
var url = '<insert url here>';
var filename = "ReportUploadTesting05.zip";
var response = UrlFetchApp.fetch(url, {
// muteHttpExceptions: true,
// validateHttpsCertificates: false,
followRedirects: true // Default is true anyway.
});
// get spreadsheet for follow up info
var Sp = SpreadsheetApp.getActiveSpreadsheet();
if (response.getResponseCode() === 200) {
// get folder details of spreadsheet for saving future files
var folderURL = getParentFolder(Sp);
var folderID = getIdFromUrl(folderURL);
var folder = DriveApp.getFolderById(folderID);
// save zip file
var blob = response.getBlob();
var file = folder.createFile(blob);
file.setName(filename);
file.setDescription("Downloaded from " + url);
var fileID = file.getId();
Logger.log(fileID);
Logger.log(blob)
// extract zip (not working)
file.setContent('application/zip')
var fileUnzippedBlob = Utilities.unzip(file); // invalid argument error occurs here
var filename = 'unzipped file'
var fileUnzipped = folder.createFile(fileUnzippedBlob)
fileUnzipped.setName(filename)
}
else {
Logger.log(response.getResponseCode());
}
}
I've followed the instructions on the Utilities page. I can get their exact example to work. I've tried creating a .zip on my computer, uploading it to Google Drive and attempted to open it unsuccessfully. Obviously there are some subtleties of using the unzip that I'm missing.
Could you help me understand this?
I was running into the same "Invalid arguments" error in my testing, so instead of using:
file.setContent('application/zip')
I used:
file.setContentTypeFromExtension();
And, that solved the problem for me. Also, as #tukusejssirs mentioned, a zip file can contain multiple files, so unzip() returns an array of blobs (as documented here). That means you either need to loop through the files, or if you know you only have one, explicitly reference it's position in the array, like this:
var fileUnzipped = folder.createFile(fileUnzippedBlob[0])
Here's my entire script, which covers both of these issues:
/**
* Fetches a zip file from a URL, unzips it, then uploads a new file to the user's Drive.
*/
function uploadFile() {
var url = '<url goes here>';
var zip = UrlFetchApp.fetch('url').getBlob();
zip.setContentTypeFromExtension();
var unzippedFile = Utilities.unzip(zip);
var filename = unzippedFile[0].getName();
var contentType = unzippedFile[0].getContentType();
var csv = unzippedFile[0];
var file = {
title: filename,
mimeType: contentType
};
file = Drive.Files.insert(file, csv);
Logger.log('ID: %s, File size (bytes): %s', file.id, file.fileSize);
var fileId = file.id;
// Move the file to a specific folder within Drive (Link: https://drive.google.com/drive/folders/<folderId>)
var folderId = '<folderId>';
var folder = DriveApp.getFolderById(folderId);
var driveFile = DriveApp.getFileById(fileId);
folder.addFile(driveFile);
}
I think the answer to your question may be found here. Is there a size limit to a blob for Utilities.unzip(blob) in Google Apps Script?
If the download is over 100 mb the full file cannot be downloaded. Due to that it will not be in the proper zip format. Throwing the cannot unzip file error.
I believe that the creation of the blob from a file (in this case the .zip file) requires the .next(); otherwise it did not work for me.
Also note that the .zip file might contain more than one file, therefore I included a for cycle.
Anyway, my working/tested solution/script is the following:
function unzip(folderName, fileZipName){
// Variables
// var folderName = "folder_name";
// var fileZipName = "file_name.zip";
var folderId = getFolderId(folderName);
var folder = DriveApp.getFolderById(folderId);
var fileZip = folder.getFilesByName(fileZipName);
var fileExtractedBlob, fileZipBlob, i;
// Decompression
fileZipBlob = fileZip.next().getBlob();
fileZipBlob.setContentType("application/zip");
fileExtractedBlob = Utilities.unzip(fileZipBlob);
for (i=0; i < fileExtractedBlob.length; i++){
folder.createFile(fileExtractedBlob[i]);
}
}
I got the following error when I tried to download a picture from a URL using Google Apps Script.
We're sorry, a server error occurred. Please wait a bit and try again.
Here is the code.
function TT() {
var response = UrlFetchApp.fetch('https://www.dropbox.com/s/g9jtm390l67uqkb/128.png?dl=1');
var blob = response.getBlob();
Logger.log(blob.getContentType());
var file = DriveApp.createFile(response);
}
Well, should try to create a file from its blob, not from the response it self.
function TT() {
var response = UrlFetchApp.fetch('https://www.dropbox.com/s/g9jtm390l67uqkb/128.png?dl=1');
var blob = response.getBlob();
Logger.log(blob.getContentType());
var file = DriveApp.createFile(blob);
}
I'v runned a test and it works perfectly.
I am sending automated report with Google spreadsheet and Google script.
So far it was working perfectly. But somehow when I try to create a new report to be emailed, the function "UrlFetchApp.fetch" return a 404. The same situation happened when I tried copying the old report.
The line with "UrlFetchApp.fetch" give me this error:
Request failed for https://docs.google.com/spreadsheets/d/1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8/pub?gid=195635557&single=true&output=pdf returned code 404. Truncated server response
It seems that I am not the only one having the issue but I cannot find any solution to it.
Here is the code:
function emailSpreadsheetAsCSV() {
var ss = SpreadsheetApp.openById("1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8");
var url = ss.getUrl();
url = url.replace(/edit$/,'');
var token = ScriptApp.getOAuthToken();
var sheets = ss.getSheets();
//make an empty array to hold your fetched blobs
var blobs = [];
for (var i=0; i<sheets.length; i++) {
var response = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8/pub?gid=195635557&single=true&output=pdf", {
headers: {
'Authorization': 'Bearer ' + token
},
'muteHttpExceptions': false
});
//convert the response to a blob and store in our array
blobs[i] = response.getBlob().setName(sheets[i].getName() + '.csv');
}
//create new blob that is a zip file containing our blob array
var zipBlob = Utilities.zip(blobs).setName(ss.getName() + '.zip');
return blobs[0];
}
Thanks a lot for your help.
Aymeric.
I've gotten this problem too and after some research, Spence Easton (question 34573295) solved my issue. I simply added this bogus call to drive so access is granted, and so the script can now get to your file.
Add this near the top before trying to grab the url:
var bogus = DriveApp.getRootFolder();
Now it runs fine with no 404 errors.
Remove the headers from the request:
var response = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8/pub?gid=195635557&single=true&output=pdf", {
'muteHttpExceptions': false
});
Check if it works for you.
You use the "pub" url so are you sure the spreadsheet is published on the web ? If you get a 404 it means the page is not published.
If file is published the bearer is not necessary as it is public now.
After I don't really understand your code because you iterate all the sheets of your file
for (var i=0; i<sheets.length; i++)
but the param "gid" (pub?gid=195635557&single=true&output=pdf) for the url in your urlfetch is fixed ?
Second point you get the file as pdf and after you create a csv ?
Why not get the file as csv directly : https://docs.google.com/spreadsheets/export?id=TheIdOfTheFile&exportFormat=csv
By adapting this code you can get the csv directly, see : https://stackoverflow.com/a/28503601/3556215
Take care you will get the first page and not others.
Stéphane
Try with:
var response = UrlFetchApp.fetch(url, options);
var result = JSON.parse(res.getContentText());