Maison > développement back-end > Golang > le corps du texte

Le téléchargement de fichiers sur Google Drive via l'API échoue

王林
Libérer: 2024-02-09 13:30:08
avant
411 Les gens l'ont consulté

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

l'éditeur php Xigua vous indique que nous pouvons parfois rencontrer des échecs lors de l'utilisation de l'API pour télécharger des fichiers sur Google Drive. Cette situation peut être provoquée par diverses raisons, telles que des problèmes de réseau, des autorisations insuffisantes, etc. Mais ne vous inquiétez pas, nous pouvons faire certaines choses pour résoudre ce problème. Ensuite, nous présenterons en détail comment télécharger avec succès des fichiers sur Google Drive via l'API, afin que tout le monde ne se soucie plus de ce problème.

Contenu de la question

J'essaie de télécharger un fichier sur mon Google Drive mais cela échoue. Je pensais avoir correctement spécifié le type MIME car j'ai trouvé qu'il s'agissait d'un problème courant, mais cela ne fonctionne toujours pas pour moi.

À propos du système de conversion : j'ai une API pour Gin-Gonic (v1.9.1) où je peux télécharger des fichiers. Le fichier est transmis avec succès du frontend/postman à l'API car je peux enregistrer avec succès le fichier que j'ai obtenu de l'API.

L'erreur que j'obtiens est :

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

J'ai la fonction suivante :

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
    }

        // ...

}
Copier après la connexion

J'ai ajouté ici un type MIME codé en dur, mais la variable fileMimeType est en fait correcte. J'ai téléchargé un fichier Test.txt contenant le contenu de Test1 (qui a également été créé avec succès lorsque je l'ai envoyé via Frontend/Postman). J'ai également essayé de spécifier le type MIME du fichier de manière dynamique ou de ne pas spécifier du tout le type MIME, mais j'obtiens toujours le même résultat.

<小时/>

J'utilise les packages suivants pour cela :

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

Éditeur :

J'ai également copié l'exemple officiel de Google, mais cela ne fonctionne toujours pas.

Solution de contournement

Il semble que l'erreur soit liée à l'authentification. Il est un peu difficile de déduire l'authentification invalide de cette erreur, mais j'ai dû modifier un peu l'algorithme d'actualisation du jeton d'actualisation pour le faire fonctionner.

<小时/>

Voici mon code de travail. Notez qu'avant d'appeler UploadFile() 函数之前,我首先检查 oauthTokenConfig.ExpiresIn pour voir si le token est toujours valide, si c'est le cas, téléchargez le fichier, sinon j'actualise d'abord le token.

Téléchargement de fichiers

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
}
Copier après la connexion

Actualiser le jeton

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
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!