首頁 >後端開發 >Golang >透過 API 將文件上傳到 Google Drive 失敗

透過 API 將文件上傳到 Google Drive 失敗

王林
王林轉載
2024-02-09 13:30:08460瀏覽

通过 API 将文件上传到 Google Drive 失败

php小編西瓜告訴大家,有時我們在使用 API 將檔案上傳到 Google Drive 的過程中可能會遇到失敗的情況。這種情況可能是由於各種原因引起的,例如網路問題、權限不足等等。不過,不用擔心,我們可以採取一些措施來解決這個問題。接下來,我們將會詳細介紹如何透過 API 將檔案成功上傳到 Google Drive,讓大家不再為這個問題煩惱。

問題內容

我正在嘗試將文件上傳到我的 Google 雲端硬碟,但失敗了。我認為我已經正確指定了 MIME 類型,因為我發現這是一個常見問題,但它仍然對我不起作用。

關於轉換系統:我有一個 Gin-Gonic (v1.9.1) 的 API,我可以在其中上傳檔案。檔案已成功從前端/郵遞員傳遞到 API,因為我可以成功保存從 API 取得的檔案。

我得到的錯誤是:

Post "https://www.googleapis.com/upload/drive/v3/files?alt=json&prettyPrint=false&uploadType=multipart": Post "": unsupported protocol scheme ""

我有以下功能:

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
    }

        // ...

}

我在這裡添加了硬編碼的 MIME 類型,但是變數 fileMimeType 實際上是正確的。我上傳了一個包含 Test1 內容的 Test.txt 檔案(當我透過 Frontend/Postman 發送該檔案時,該檔案也已成功建立)。我還嘗試動態指定檔案 MIME 類型或根本不指定 MIME 類型,但總是得到相同的結果。

我為此使用以下軟體包:

  • Go版本:go1.21.1 darwin/arm64
  • go list -m golang.org/x/oauth2: v0.13.0
  • go 列表 -m google.golang.org/api: v0.147.0
    • google.golang.org/api/drive/v3
    • google.golang.org/api/googleapi
    • #google.golang.org/api/option

編輯:

我也複製了Google官方的例子,還是不行。

解決方法

看起來錯誤與身份驗證有關。從這個錯誤中推斷出無效的身份驗證有點困難,但我必須稍微更改一下刷新令牌的刷新演算法才能使其正常工作。

這是我的工作程式碼。請注意,在調用UploadFile() 函數之前,我首先檢查oauthTokenConfig.ExpiresIn

以查看令牌是否仍然有效,如果是,則上傳文件,否則我首先刷新令牌。

檔案上傳

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
}

刷新令牌###
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
}

以上是透過 API 將文件上傳到 Google Drive 失敗的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除