401 未经授权 - Google 驱动器 API

401 Unauthorized - Google Drive API

我是第一次使用 Google API,尝试使用文件对象 "downloadUrl" 属性 下载文件时遇到问题。我目前正在将 "Service Account" 选项与关联的服务帐户电子邮件和 P12 证书一起使用。

但是,URL 返回了“https://doc-08-68-docs.googleusercontent.com/docs/securesc/bteg36c1tifegg79l2ov17og25612tet/gk7kn52ahe4d0to7d6hte9f0f2hv47e4/1434132000000/11750183130219432819/11750183130219432819/0BziIKv2_NWCxc3RhcnRlcl9maWxl?e=download&gd=true”returns 401 - 未经授权的响应。

Imports System.Collections.Generic
Imports System.Security.Cryptography.X509Certificates
Imports System.IO

Imports Google.Apis.Drive.v2
Imports Google.Apis.Drive.v2.Data
Imports Google.Apis.Services
Imports Google.Apis.Auth.OAuth2

Namespace Videos

    Partial Class List
        Inherits System.Web.UI.UserControl

        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

            Const serviceAccountEmail As String = "@developer.gserviceaccount.com"

            Dim certificate = New X509Certificate2(
                Server.MapPath("~/bin/key.p12"),
                "notasecret",
                X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.Exportable
            )

            Dim credential = New ServiceAccountCredential(
               New ServiceAccountCredential.Initializer(serviceAccountEmail) With {
                   .Scopes = New String() {DriveService.Scope.Drive}
               }.FromCertificate(certificate)
            )

            Dim service = New DriveService(
                New BaseClientService.Initializer() With {
                    .HttpClientInitializer = credential,
                    .ApplicationName = "LexVid-VideoEncode/1.0"
                }
            )

            UxFiles.DataSource = RetrieveAllFiles(service)
            UxFiles.DataBind()

        End Sub

        Public Shared Function RetrieveAllFiles(service As DriveService) As List(Of Data.File)

            Dim result = New List(Of Data.File)()
            Dim request As FilesResource.ListRequest = service.Files.List()

            Do

                Try

                    Dim files As FileList = request.Execute()

                    result.AddRange(files.Items)
                    request.PageToken = files.NextPageToken

                Catch e As Exception
                    request.PageToken = Nothing
                End Try

            Loop While (Not String.IsNullOrEmpty(request.PageToken))

            Return result

        End Function


        Public Shared Function DownloadFile(ByVal service As DriveService, ByVal file As Data.File) As System.IO.Stream

            If (Not String.IsNullOrEmpty(file.DownloadUrl)) Then

                Try

                    Dim x = service.HttpClient.GetByteArrayAsync(file.DownloadUrl)
                    Dim result As [Byte]() = x.Result

                    Return New MemoryStream(result)

                Catch e As Exception
                    Return Nothing
                End Try

            Else
                Return Nothing
            End If

        End Function

        Protected Sub UxFiles_ItemDataBound(ByVal sender As Object, ByVal e As ListViewItemEventArgs) Handles UxFiles.ItemDataBound

            Dim dataItem = CType(e.Item.DataItem, Data.File)

            Dim file = CType(e.Item.FindControl("UxFile"), HyperLink)
            file.NavigateUrl = dataItem.DownloadUrl
            file.Text = dataItem.Title

        End Sub

    End Class

End Namespace

我通过反复试验解决了这个问题。虽然我现在正在手动构建链接,因此甚至不再需要请求令牌。但是,我在这里发帖以防其他人寻求解决类似问题。

Imports System.Collections.Generic
Imports System.Security.Cryptography.X509Certificates
Imports System.IO
Imports System.Threading

Imports Google.Apis.Drive.v2
Imports Google.Apis.Drive.v2.Data
Imports Google.Apis.Services
Imports Google.Apis.Auth.OAuth2

Namespace Videos

    Partial Class List
        Inherits System.Web.UI.UserControl

        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

            Const serviceAccountEmail As String = "@developer.gserviceaccount.com"

            Dim certificate = New X509Certificate2(
                Server.MapPath("~/bin/key.p12"),
                "notasecret",
                X509KeyStorageFlags.MachineKeySet Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.Exportable
            )

            Dim credential As ServiceAccountCredential = New ServiceAccountCredential(
            New ServiceAccountCredential.Initializer(serviceAccountEmail) With {
                .Scopes = New String() {DriveService.Scope.Drive}
            }.FromCertificate(certificate)
            )

            If (credential.RequestAccessTokenAsync(CancellationToken.None).Result) Then

                Dim service = New DriveService(
                    New BaseClientService.Initializer() With {
                        .HttpClientInitializer = credential,
                        .ApplicationName = "LexVid-VideoEncode/1.0"
                    }
                )

                UxFiles.DataSource = RetrieveAllFiles(service)
                UxFiles.DataBind()

            End If

        End Sub

        Public Shared Function RetrieveAllFiles(service As DriveService) As List(Of Data.File)

            Dim result = New List(Of Data.File)()
            Dim request As FilesResource.ListRequest = service.Files.List()

            Do

                Try

                    Const folderID As String = "0B5RLR6VRZsR4fkE5QjVFajg2dzZOMXZLYkNZUVdGbEtNODF0XzVBVGdjMW9ISDF5OE9kM0E"
                    request.Q = String.Format("'{0}' in parents and trashed=false", folderID)
                    Dim files As FileList = request.Execute()

                    result.AddRange(files.Items)
                    request.PageToken = files.NextPageToken

                Catch e As Exception
                    request.PageToken = Nothing
                End Try

            Loop While (Not String.IsNullOrEmpty(request.PageToken))

            Return result

        End Function

        Protected Sub UxFiles_ItemDataBound(ByVal sender As Object, ByVal e As ListViewItemEventArgs) Handles UxFiles.ItemDataBound

            Dim dataItem = CType(e.Item.DataItem, Data.File)

            Const folderID As String = "0B5RLR6VRZsR4fkE5QjVFajg2dzZOMXZLYkNZUVdGbEtNODF0XzVBVGdjMW9ISDF5OE9kM0E"

            Dim file = CType(e.Item.FindControl("UxFile"), HyperLink)
            file.NavigateUrl = String.Format("http://googledrive.com/host/{0}/{1}", folderID, dataItem.Title)
            ' Large files prompt for virus scan; no bypass available.
            ' file.NavigateUrl = String.Format("https://drive.google.com/uc?export=download&id={0}", dataItem.Id)
            file.Text = dataItem.Title

        End Sub

    End Class

End Namespace