Home >Backend Development >Golang >File upload to Google Drive via API fails
php editor Xigua tells you that sometimes we may encounter failures when using the API to upload files to Google Drive. This situation may be caused by various reasons, such as network problems, insufficient permissions, etc. But don’t worry, there are some things we can do to fix this problem. Next, we will introduce in detail how to successfully upload files to Google Drive through the API, so that everyone will no longer worry about this problem.
I'm trying to upload a file to my Google Drive but it's failing. I thought I had specified the MIME type correctly because I found this to be a common problem, but it still doesn't work for me.
About the conversion system: I have an API for Gin-Gonic (v1.9.1) where I can upload files. The file is successfully passed from the frontend/postman to the API as I can successfully save the file I got from the API.
The error I get is:
Post "https://www.googleapis.com/upload/drive/v3/files?alt=json&prettyPrint=false&uploadType=multipart": Post "": unsupported protocol scheme ""
I have the following function:
func (c *Client) UploadFile(oauthTokenConfig GoogleOauthTokenConfig, parentFolderId string, fileHeader *multipart.FileHeader) (*string, error) { svc, err := drive.NewService(context.Background(), option.WithHTTPClient( oauthTokenConfig.Config.Client( context.Background(), &oauth2.Token{ AccessToken: oauthTokenConfig.AccessToken, TokenType: oauthTokenConfig.TokenType, RefreshToken: oauthTokenConfig.RefreshToken, Expiry: oauthTokenConfig.ExpiresIn, }, )), ) if err != nil { return nil, err } fileExtension := filepath.Ext(fileHeader.Filename) fileName := strings.TrimSuffix(fileHeader.Filename, fileExtension) fileMimeType := fileHeader.Header.Get("Content-Type") uploadFileMetaData := drive.File{ Name: fmt.Sprintf("%s%s", fileName, fileExtension), // fmt.Sprintf("%s_%s%s", fileName, uuid.New().String(), fileExtension), Parents: []string{parentFolderId}, MimeType: fileMimeType, } file, err := fileHeader.Open() if err != nil { return nil, err } defer file.Close() fileResult, err := svc.Files. Create(&uploadFileMetaData). Media(file, googleapi.ContentType("text/plain")). Do() if err != nil { return nil, err // here I get the error } // ... }
I added a hardcoded MIME type here, but the variable fileMimeType
is actually correct. I uploaded a Test.txt file containing the contents of Test1 (which was also created successfully when I sent it via Frontend/Postman). I've also tried specifying the file MIME type dynamically or not specifying the MIME type at all, but always get the same result.
I use the following packages for this:
go1.21.1 darwin/arm64
edit:
I also copied Google’s official example, but it still doesn’t work.
Looks like the error is related to authentication. It's a bit difficult to deduce the invalid authentication from this error, but I had to change the refresh token's refresh algorithm a bit to get it to work.
This is my working code. Note that before calling the UploadFile()
function, I first check oauthTokenConfig.ExpiresIn
to see if the token is still valid, if so, upload the file, otherwise I first refresh the token .
File Upload
func (c *Client) UploadFile(oauthTokenConfig GoogleOauthTokenConfig, parentFolderId string, file *multipart.FileHeader) (*string, error) { svc, err := drive.NewService(context.Background(), option.WithHTTPClient( oauthTokenConfig.Config.Client( context.Background(), &oauth2.Token{ AccessToken: oauthTokenConfig.AccessToken, TokenType: oauthTokenConfig.TokenType, RefreshToken: oauthTokenConfig.RefreshToken, Expiry: oauthTokenConfig.ExpiresIn, }, )), ) if err != nil { return nil, fmt.Errorf("failed to create drive-service: %s", err.Error()) } fileExtension := filepath.Ext(file.Filename) fileName := strings.TrimSuffix(file.Filename, fileExtension) uploadFile := drive.File{ Name: fmt.Sprintf("%s_%s%s", fileName, uuid.New().String(), fileExtension), Parents: []string{parentFolderId}, } fileContent, err := file.Open() if err != nil { return nil, fmt.Errorf("failed to open file: %s", err.Error()) } fileResult, err := svc.Files.Create(&uploadFile).Media(fileContent).Do() if err != nil { return nil, fmt.Errorf("failed to create file: %s", err.Error()) } uploadedFile, err := svc.Files.Get(fileResult.Id).Fields("webViewLink").Do() if err != nil { return nil, fmt.Errorf("failed to get file: %s", err.Error()) } return &uploadedFile.WebViewLink, nil }
Refresh Token
func (c *Client) RefreshToken(oauthTokenConfig GoogleOauthTokenConfig) (*GoogleOauthTokenConfig, error) { ctx := context.Background() config := oauth2.Config{ ClientID: c.ClientId, ClientSecret: c.ClientSecret, RedirectURL: oauthTokenConfig.Config.RedirectURL, Scopes: []string{"https://www.googleapis.com/auth/drive"}, Endpoint: google.Endpoint, } token := &oauth2.Token{ AccessToken: oauthTokenConfig.AccessToken, TokenType: oauthTokenConfig.TokenType, RefreshToken: oauthTokenConfig.RefreshToken, Expiry: oauthTokenConfig.ExpiresIn, } tokenSource := config.TokenSource(ctx, token) updatedToken, err := tokenSource.Token() if err != nil { return nil, err } return &GoogleOauthTokenConfig{ Config: config, AccessToken: updatedToken.AccessToken, RefreshToken: updatedToken.RefreshToken, ExpiresIn: updatedToken.Expiry, TokenType: updatedToken.TokenType, }, nil }
The above is the detailed content of File upload to Google Drive via API fails. For more information, please follow other related articles on the PHP Chinese website!