Maison  >  Article  >  développement back-end  >  Le téléchargement de fichiers sur Google Drive via l'API échoue

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

王林
王林avant
2024-02-09 13:30:08412parcourir

通过 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 ""

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
    }

        // ...

}

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
}

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
}

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer