Skip to content

Instantly share code, notes, and snippets.

@denilsonsa
Last active December 18, 2022 18:32
Show Gist options
  • Star 42 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
  • Save denilsonsa/8134679 to your computer and use it in GitHub Desktop.
Save denilsonsa/8134679 to your computer and use it in GitHub Desktop.
Google Apps Script to upload a file from an URL directly to Google Drive.
// url_to_drive.gs
// Google Apps Script
// Allows uploading a URL directly to Google Drive.
//
// Live link:
// https://script.google.com/macros/s/AKfycbzvhbHS4hnWPVBDHjQzZHA0qWq0GR-6hY7TbYsNto6hZ0MeAFZt/exec
//
// Source-code:
// https://gist.github.com/denilsonsa/8134679
// https://script.google.com/d/1Ye-OEn1bDPcmeKSe4gb0YSK83RPMc4sZJt79SRt-GRY653gm2qVUptoE/edit
//
// Other solutions written by other people:
// https://ifttt.com/channels/google_drive/actions/78
// https://sites.google.com/site/fileurltodrive/
// Note: I wrote this script without looking at the source-code of other solutions.
function getFilenameFromURL(url) {
// (host-ish)/(path-ish/)(filename)
var re = /^https?:\/\/([^\/]+)\/([^?]*\/)?([^\/?]+)/;
var match = re.exec(url);
if (match) {
return unescape(match[3]);
}
return null;
}
function getFilenameFromContentDisposition(header) {
// It does not support escaped double-quotes inside the filename.
// It certainly does not conform to the specs.
var re = /; *filename=("[^"]+"|[^ ;]+)/;
var match = re.exec(header)
if (match) {
return match[1];
}
return null;
}
function uploadToDrive(url, folderid, filename) {
var msg = '';
var response;
try {
response = UrlFetchApp.fetch(url, {
// muteHttpExceptions: true,
// validateHttpsCertificates: false,
followRedirects: true // Default is true anyway.
});
} catch(e) {
return e.toString();
}
if (response.getResponseCode() === 200) {
if (!filename) {
// TODO: try content-disposition.
filename = getFilenameFromURL(url);
}
if (!filename) {
msg += 'Aborting: Filename not detected. Please supply a filename.\n'
} else {
var folder = DriveApp.getRootFolder();
if (folderid) {
folder = DriveApp.getFolderById(folderid);
}
var blob = response.getBlob();
var file = folder.createFile(blob);
file.setName(filename);
file.setDescription("Downloaded from " + url);
var headers = response.getHeaders();
var content_length = NaN;
for (var key in headers) {
if (key.toLowerCase() == 'Content-Length'.toLowerCase()) {
content_length = parseInt(headers[key], 10);
break;
}
}
var blob_length = blob.getBytes().length;
msg += 'Saved "' + filename + '" (' + blob_length + ' bytes)';
if (!isNaN(content_length)) {
if (blob_length < content_length) {
msg += ' WARNING: truncated from ' + content_length + ' bytes.';
} else if (blob_length > content_length) {
msg += ' WARNING: size is greater than expected ' + content_length + ' bytes from Content-Length header.';
}
}
msg += '\nto folder "' + folder.getName() + '".\n';
}
} else {
msg += 'Response code: ' + response.getResponseCode() + '\n';
}
// Debug: printing response headers.
// msg += JSON.stringify(response.getHeaders(), undefined, 2) + '\n';
return msg;
}
function newPanel(app, msg, url, folderid, filename) {
var form = app.createFormPanel();
var title = app.createLabel('Upload URL to Google Drive (10MB limit)');
title.setStyleAttributes({
fontSize: '2em',
margin: '0 1ex'
});
var extra_links = app.createFlowPanel();
extra_links.add(app.createInlineLabel('Written by '));
extra_links.add(app.createAnchor('Denilson Sá', 'http://about.me/denilsonsa'));
extra_links.add(app.createInlineLabel(', source-code available at '));
extra_links.add(app.createAnchor('Google Apps Script', 'https://script.google.com/d/1Ye-OEn1bDPcmeKSe4gb0YSK83RPMc4sZJt79SRt-GRY653gm2qVUptoE/edit'));
extra_links.add(app.createInlineLabel(' and at '));
extra_links.add(app.createAnchor('GitHub Gist', 'https://gist.github.com/denilsonsa/8134679'));
extra_links.add(app.createInlineLabel('. '));
var text = app.createLabel(msg);
text.setId('text');
text.setStyleAttribute('white-space', 'pre-wrap');
var url_label = app.createLabel('URL:');
var url_textbox = app.createTextBox();
url_textbox.setName('url');
url_textbox.setId('url');
url_textbox.setStyleAttribute('width', '99%');
url_textbox.setValue(url);
var filename_label = app.createLabel('Filename: (blank to auto-detect)');
var filename_textbox = app.createTextBox();
filename_textbox.setName('filename');
filename_textbox.setId('filename');
filename_textbox.setStyleAttribute('width', '99%');
filename_textbox.setValue(filename);
var folderid_label = app.createLabel('Folder ID: (the alphanumeric string at the Google Drive URL for a folder; blank for root folder)');
var folderid_textbox = app.createTextBox();
folderid_textbox.setName('folderid');
folderid_textbox.setId('folderid');
folderid_textbox.setStyleAttribute('width', '99%');
folderid_textbox.setValue(folderid);
var button = app.createSubmitButton('Upload to Drive');
var panel = app.createVerticalPanel();
panel.setWidth("99%")
panel.setSpacing(5);
panel.add(title);
panel.add(extra_links);
panel.add(url_label);
panel.add(url_textbox);
panel.add(filename_label);
panel.add(filename_textbox);
panel.add(folderid_label);
panel.add(folderid_textbox);
panel.add(button);
panel.add(text);
form.add(panel);
if (app) {
app.add(form);
}
return panel;
}
function getOrPost(e, app, is_post) {
app.setTitle('Upload URL to Google Drive');
var msg = '';
var url = '';
var folderid = '';
var filename = '';
if (is_post) {
url = e.parameter.url.trim();
folderid = e.parameter.folderid.trim();
filename = e.parameter.filename.trim();
msg += uploadToDrive(url, folderid, filename);
}
// msg += Logger.getLog();
newPanel(app, msg, url, folderid, filename);
}
function doGet(e) {
var app = UiApp.createApplication();
getOrPost(e, app, false);
return app;
}
function doPost(e) {
var app = UiApp.getActiveApplication();
getOrPost(e, app, true);
return app;
}
@askmrsinh
Copy link

This is exactly what I was looking for (somewhat similar to http://ctrlq.org/save/). Thanks for sharing.

@haizrul
Copy link

haizrul commented Jan 28, 2016

How do i change the upload limit? Its only 10Mb

@denilsonsa
Copy link
Author

@haizrul: AFAIK, you can't change. It is an undocumented limitation of the UrlFetchApp.fetch() API. If someone knows a solution, feel free to message me.

(Note: comments on Gist do not send notifications, so I may never see comments here; there are several other ways to contact me.)

@vishnu1991
Copy link

@denilsonsa @haizrul
i think we have to change "10" in the LINE 74
content_length = parseInt(headers[key], 10);

Example for 20 mb upload size ,update LINE 74 with this:
content_length = parseInt(headers[key], 20);

@denilsonsa
Copy link
Author

@vishnu1991 parseInt's second argument is the radix (i.e. the base) of the number to be converted from string to int. In this case, base 10, which means decimal, which means digits go from zero to nine.

As I mentioned before, the 10MB limit is imposed by the Google API itself. There is nothing in this script that limits the size.

@kurokirasama
Copy link

kurokirasama commented Apr 30, 2017

@denilsonsa Hello,

i'm trying to use this script to download torrent files i get in my email. I successfully obtained url (string), folder id and filename, but i get the following error from this script:
Exception: No valid argument:url

any ideas ? please

if i paste url in explorer, the file gets downloaded...

@edley163
Copy link

edley163 commented May 2, 2017

@denilsonsa I'm trying to use this to automatically download CSV files from download URLs in emails that i receive. I think this script does what i am looking for but i don't really understand how to use it to do that. Can anyone help? Thank you

@laxmandeokar
Copy link

How do i change the upload limit? Its only 10Mb
can i upload more than 100MB ?

@jobdiogenes
Copy link

why not use just UrlFetchApp?
like?
function uploadFileFromUrl(url) {
var folderID = "jhguguytel3i72t4ldutg3u"; // your Folder ID
var folder = DriveApp.getFolderById(folderID);
var httpoptions = {
method:"get",
muteHttpExceptions:true
};
var resp = UrlFetchApp.fetch(url,httpoptions);
var head = resp.getAllHeaders();
if (resp.getResponseCode()==200)
if (head["Content-Length"] >"0") {
var pic = resp.getBlob().setName(nome+"-"+lattesid)
var result = pasta.createFile(pic);
}
}

@cool125
Copy link

cool125 commented Sep 23, 2017

i am not an expert in coding.. kindly someone will explain me in details that how to modify script values ?

and i have a questions,

  • can we use this google drive as FTP alternate? if yes, pleaser refer me to the solution.

@X7md
Copy link

X7md commented Oct 3, 2020

image
What should I do now? with UiApp?

@X7md
Copy link

X7md commented Oct 3, 2020

image
What should I do now? with UiApp?

Never mind... I just delete it, and edit some little then it's worked! 😅

@ianthomaz
Copy link

why not use just UrlFetchApp?
like?
function uploadFileFromUrl(url) {
var folderID = "jhguguytel3i72t4ldutg3u"; // your Folder ID
var folder = DriveApp.getFolderById(folderID);
var httpoptions = {
method:"get",
muteHttpExceptions:true
};
var resp = UrlFetchApp.fetch(url,httpoptions);
var head = resp.getAllHeaders();
if (resp.getResponseCode()==200)
if (head["Content-Length"] >"0") {
var pic = resp.getBlob().setName(nome+"-"+lattesid)
folder.createFile(pic);
}
}

// ao final vc estrava chamando a VAR "pasta" que não existia... troquei para Folder.
// Ao novatos como eu.... lembrar de definir também "Nome" e "LattesID"
// MARAVILHOSO O CÓDIGO !
// Agora vou tentar colocar ele num loop.... vamos que vamos :D

@TeamsAcademy
Copy link

@X7md May I know how you fix that, please?

@denilsonsa
Copy link
Author

For whoever comes to this Gist in the future: I haven't used this code in over five years, and it's unlikely I'm gonna use it again. The UiApp has been deprecated (Thankfully! That thing was annoying to use.), and I have no intention of rewriting this code using HtmlService. In fact, I have no intention of using this code ever again, as I don't think I have the need for it anymore.

(A little bit of history: back then, I had terrible Internet connection, so downloading stuff directly to Google Drive was significantly faster than downloading first to my computer and then uploading. Nowadays my Internet connection is fast and reliable, and I have little to no reason to download anything directly to Google Drive. Additionally, silently truncating the file to 10MB is inconvenient.)

Feel free to use this code as a basis for your own version, and even post a comment here pointing to your fixed/updated version. Have fun writing your own version!

@YOSI-COHEN
Copy link

איפה אני מכניס את הקישור שאני רוצה להוריד

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment