7

I have a zip file stored on Google Drive (it is shared publicly). I want to know how to download it in Golang. This current code just creates a blank file named "file.zip":

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    url := "https://docs.google.com/uc?export=download&id=0B2Q7X-dUtUBebElySVh1ZS1iaTQ"
    fileName := "file.zip"
    fmt.Println("Downloading file...")

    output, err := os.Create(fileName)
    defer output.Close()

    response, err := http.Get(url)
    if err != nil {
        fmt.Println("Error while downloading", url, "-", eerrror)
        return
    }
    defer response.Body.Close()

    n, err := io.Copy(output, response.Body)

    fmt.Println(n, "bytes downloaded")
}
DanielTA
  • 6,038
  • 3
  • 23
  • 27
  • 1
    what does the error variable have? – Jeremy Wall Aug 11 '13 at 22:42
  • I tried running your code locally. The response status is 403 Forbidden. I don't know what is causing that though. Also, never use "error" as a variable. You are shadowing the universe "error" type. – Stephen Weinberg Aug 12 '13 at 02:05
  • Huh, well why would it say that? I shared the file publically. And thanks for the heads up about the error variable, I will change it to err. – DanielTA Aug 12 '13 at 02:27
  • It's possible that Google is doing something which interacts with the browser somehow. Maybe they're detecting that you're not using a browser and rejecting you on that basis. – joshlf Aug 12 '13 at 04:43

3 Answers3

9

This appears to be a bug, either with Google drive or with golang, I'm not sure which!

The problem is that the first URL you gave redirects to a second URL which looks something like this

https://doc-00-c8-docs.googleusercontent.com/docs/securesc/ha0ro937gcuc7l7deffksulhg5h7mbp1/8i67l6m6cdojptjuh883mu0qqmtptds1/1376330400000/06448503420061938118/*/0B2Q7X-dUtUBebElySVh1ZS1iaTQ?h=16653014193614665626&e=download

Note the * in the URL which is legal according to this stack overflow question. However it does have a special meaning as a delimeter.

Go fetches the URL with the * encoded as %2A like this

https://doc-00-c8-docs.googleusercontent.com/docs/securesc/ha0ro937gcuc7l7deffksulhg5h7mbp1/8i67l6m6cdojptjuh883mu0qqmtptds1/1376330400000/06448503420061938118/%2A/0B2Q7X-dUtUBebElySVh1ZS1iaTQ?h=16653014193614665626&e=download

Which Google replies "403 Forbidden" to.

Google doesn't seem to be resolving the %2A into a *.

According to this article on wikipedia reserved characters (of which * is one) used in a URI scheme: if it is necessary to use that character for some other purpose, then the character must be percent-encoded.

I'm not enough of an expert on this to say who is right, but since Google wrote both parts of the problem it is definitely their fault somewhere!

Here is the program I was using for testing

Community
  • 1
  • 1
Nick Craig-Wood
  • 52,955
  • 12
  • 126
  • 132
  • Thanks for the explanation. I have found a solution. I will post it soon. – DanielTA Aug 13 '13 at 01:27
  • It's 2015, and google still does not accept `%2A`. It was a hellish experience to track down the problem, since traffic is secured with HTTPS. Thanks for this answer, it was really helpful! – GreenScape Dec 22 '15 at 09:31
6

I found the solution. Use: https://googledrive.com/host/ID

Instead of: https://docs.google.com/uc?export=download&id=ID

DanielTA
  • 6,038
  • 3
  • 23
  • 27
  • Thank You so much!!! I have been searching the internet for 2 hours to solve this problem and you have been the only one to do this. Can you please provide the source of your answer? – Cool_Coder Dec 01 '13 at 13:57
  • Sorry, it was awhile ago. I think it was some Google help page relating to something else and I figured I would see if it would work for this as well, and it did. – DanielTA Dec 04 '13 at 21:19
3

I'm still investigating on why this is happening, in the meanwhile you can use this workaround:

http://play.golang.org/p/SzGBAiZdGJ

CheckRedirect is called when a redirect happens and you can add an Opaque path to avoid having the URL url-encoded.

Francesc