5

I am testing how to update user picture using the Admin SDK Directory Service with Google Apps Scripts with the following function:

function updatePhoto(){
  var fileId = 'XXXXXXXXXXXXXXXXXXX';
  var b = DocsList.getFileById(fileId).getBlob();
  var encoded = Utilities.base64Encode(b.getBytes());

  encoded = encoded.replace(/\//g,'_').replace(/\+/g,'-').replace(/\=/g,'*');
  AdminDirectory.Users.Photos.update({
    "photoData": encoded },'harry.potter@abc.edu.hk');
}

However, it doesn't always work. Whenever there is padding in the base64 encoded string, it fails. Referring to Google's document (https://developers.google.com/admin-sdk/directory/v1/reference/users/photos/update), I am a bit confused with the descriptions. It says:

  1. The equals sign (=) character is replaced with the asterisk (*).
  2. For padding, the period (.) character is used instead of the RFC-4648 baseURL definition which uses the equals sign (=) for padding. This is done to simplify URL-parsing.

What should be actually done? (=) is used for padding in Base64. So, should I use (*) or (.)? I did try to replace (=) with (.) but no luck.

Can anyone help?


It is so strange. It works when i do not replace (=).

function updatePhoto(){
  var fileId = 'XXXXXXXXXXXXXXXXXXX';
  var b = DocsList.getFileById(fileId).getBlob();
  var encoded = Utilities.base64Encode(b.getBytes());

  encoded = encoded.replace(/\//g,'_').replace(/\+/g,'-');
  AdminDirectory.Users.Photos.update({
    "photoData": encoded },'harry.potter@abc.edu.hk');

}

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
user2054013
  • 133
  • 3
  • 3
  • 8

4 Answers4

8

The API requires you to use URL-safe base64 encoding. After doing the base64 encoding, try replacing / with _ and + with -. Details at:

https://developers.google.com/admin-sdk/directory/v1/reference/users/photos/update

Jay Lee
  • 13,415
  • 3
  • 28
  • 59
  • Thanks a lot. It works. I got confused by that description and the error message. After adding the following line before the AdminDirectory line, it works. encoded = encoded.replace(/\//g,'_').replace(/\+/g,'-').replace(/\=/g,'*'); " – user2054013 Mar 03 '14 at 00:35
  • :) Oh. I just found that it doesn't work for all photos. – user2054013 Mar 03 '14 at 01:40
  • 1
    I just figured out the problem came from the padding. Whenever there is padding, it fails. I have edited the question accordingly. – user2054013 Mar 03 '14 at 03:56
  • 1
    This is so funny. I kinda solved that problem by simply leave (=) unchanged. Strange. encoded = encoded.replace(/\//g,'_').replace(/\+/g,'-'); – user2054013 Mar 03 '14 at 08:50
  • what about the german characters like ä,ü,ö & ß? – AJ007 Jul 01 '22 at 13:17
4

I know that this is quite old, but I'm working in something similar and I want to share my solution. You can use this function to convert your string to a base64safeurl string:

protected static string Base64ForUrlEncode(string str)
        {

            StringBuilder result = new StringBuilder(Convert.ToBase64String(Encoding.ASCII.GetBytes(str)).TrimEnd('='));
            result.Replace('+', '-');
            result.Replace('/', '_');
            return result.ToString();
        }

More info here: http://www.codeproject.com/Tips/76650/Base-base-url-base-url-and-z-base-encoding

Note: This is C# code, so this solution is for .NET developments.

Daniel Marín
  • 1,369
  • 14
  • 36
  • This only replaces first occurrence,the code in the comments does it globally. – Serge insas Sep 25 '14 at 05:32
  • Sorry, but I don't understand. Can you explain what do you mean with "first occurrence"? – Daniel Marín Sep 25 '14 at 11:20
  • result.Replace('+', '-'); replaces only first occurrence of +, if you want all the + in a string to be replaced you need to use the g flag like in the answer below (g comes for 'global') – Serge insas Sep 25 '14 at 11:29
  • [.NET documentation](http://msdn.microsoft.com/en-us/library/fk49wtc1(v=vs.110).aspx) says: "Returns a new string in which all occurrences of a specified string in the current instance are replaced with another specified string." – Daniel Marín Sep 26 '14 at 12:02
  • .NET framework is not javascript...Look at javascript documentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace see the 'g' flag. – Serge insas Sep 26 '14 at 12:23
  • 1
    I know. My solution is in .NET. Like I said in the answer, I just wanted to share it. Could be useful to someone. I should edit my answer and make clear that is C# code. – Daniel Marín Oct 03 '14 at 07:54
  • Actually, you should not post answers for different languages than the question is about. This is definitely *not* useful to someone who would find this question, looking for Javascript. Please pay close attention to what languages/tags are used in a question in the future. – Andrew Barber Oct 08 '14 at 16:54
  • what about the german characters like ä,ü,ö & ß? – AJ007 Jul 01 '22 at 13:17
2

To add to @Jay lee's and @Daniel Marin's answers:

if you are using Python to encode, you can use:

base64.urlsafe

function, and in Java, you can use:

Base64.encodeBase64URLSafeString(byte[] binaryData)
Good Lux
  • 896
  • 9
  • 19
0

RFC 4648 specifies "web-safe" base64 and calls it "base64url": https://datatracker.ietf.org/doc/html/rfc4648#section-5

Florian Sesser
  • 5,972
  • 1
  • 25
  • 26