Easiest way to get file ID from URL on Google Apps

2019-01-06 15:02发布

问题:

Here is what I'm trying to do: given a Google document URL, I want to get the document ID to create a copy on Google Drive. I know I can achieve that by some regex or replacing on the URL, but as there are several different forms to represent the same document in a URL, I wanted to find a generic solution.

Currently, that's the best I could think:

function getFileIdFromUrl(url) {
  try {
    return getDocIdFromUrl(url);
  } catch (e) {
    return getSpreadsheetIdFromUrl(url);
  }
}

function getDocIdFromUrl(url) {
  var doc = null;
  try {
    doc = DocumentApp.openByUrl(url);
  } catch (e) {
    doc = DocumentApp.openByUrl(url + "/edit");
  }
  return doc.getId();
}

function getSpreadsheetIdFromUrl(url) {
  var spreadsheet = null;
  try {
    spreadsheet = SpreadsheetApp.openByUrl(url);
  } catch (e) {
    spreadsheet = SpreadsheetApp.openByUrl(url + "/edit");
  }
  return spreadsheet.getId();
}

function copy(url) { // may throw an exception if the URL is invalid or private
   var id = getFileIdFromUrl(url);
   var file = DriveApp.getFileById(id);
   file.makeCopy().setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
}

The problem is that my solution only covers documents and spreadsheets, I would like to do the same with any uploaded file, for example:

https://docs.google.com/file/d/0B-FYu_D7D7x4REdtRVEzVH0eU0/edit

In short, I wanted something like that:

DriveApp.getFileByUrl(url).makeCopy();

Does anyone know if it's possible?

Any safe solution to extract the file ID from the file URL would fit as well for me.

Thanks

回答1:

DriveApp is indeed missing a getFileByUrl (and also folder for that matter). You may want to open an enhancement request on Apps Script issue tracker.

But what I do on my scripts (since these openByUrl functions are somewhat new), is to get the id using a regex. Like this.

function getIdFromUrl(url) { return url.match(/[-\w]{25,}/); }

This regex works for any google url I've tried: Drive url for folders and files, Fusion Tables, Spreadsheets, Docs, Presentations, etc. It just looks for anything in a string that "looks like" a Google key. That is, any big enough string that has only (google key) valid characters in it.

Also, it works even if it receives the ID directly, instead of the URL. Which is useful when you're asking the link from the user, as some may paste the id directly instead of the url and it still works.



回答2:

The url is something like this and file id is present in this pattern "/d/XXXXXXXX/" for almost all GoogleDrive/Docs links:
https://drive.google.com/file/d/0B3tB9BU9FRnpcTJmS2FoaktsQzA/view

Using below function, we can get the '/d/fileid/' and then truncate '/d/' from begining and '/' from end.

public static string getIdFromUrl(string url)
{
    Regex r = new Regex(@"\/d\/(.+)\/", RegexOptions.IgnoreCase);
    Match m = r.Match(url);
    return m.ToString().TrimStart('/', 'd').Trim('/');
}


回答3:

There are some more URL extensions not covered above which can contain IDs.

https://drive.google.com/drive/folders/ and https://drive.google.com/open?id= and https://drive.google.com/a/domain.edu.vn/folderview?id=

I thought I'd add my solution which builds on this idea, and covers the above two extensions, as well as the ones using /d/

function getIdFrom(url) {
  var id = "";
  var parts = url.split(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/);
  if (url.indexOf('?id=') >= 0){
     id = (parts[6].split("=")[1]).replace("&usp","");
     return id;
   } else {
   id = parts[5].split("/");
   //Using sort to get the id as it is the longest element. 
   var sortArr = id.sort(function(a,b){return b.length - a.length});
   id = sortArr[0];
   return id;
   }
 }


回答4:

I don't have enough reputation to comment on the accepted answer, but the accepted answer from Henrique G. Abreu fails when a Drive URL contains the domain name and the domain name exceeds 25 characters (just found this out the hard way :)

It has been very reliable otherwise and I think is the most elegant and robust among those provided here.

So, expanding on the accepted answer, the following regex will get the last occurrence of a string of word characters or hyphens that is at least 25 characters long, that is immediately preceded by a character that isn't a non word character or a hyphen, and followed optionally by the same type of character, and whatever other junk might come at the end:

/.*[^-\w]([-\w]{25,})[^-\w]?.*/

This LOSES the characteristic of the accepted answer that it will work when passed an ID only, however that's not a use case I require. It works for all different types of Drive, Docs, Sheets URLs for both documents and folders that I've tested.



回答5:

I just wanted to add the function I created based on the two given answers, because neither was quite what I was looking for.

function templateIdFrom(url) {
  var parts = url.match(/\/d\/(.+)\//);
  if (parts == null || parts.length < 2) {
    return url;
  } else {
    return parts[1];
  }
}

This gets the part after /d/ and up until the next /, which is how the document URLs always contain their IDs. If no match is found for this, then we simply return the original param, which is assumed to be the ID.