熟悉V3 YouTube API的任何人都会建议我可能做错了什么:
Dim Service As YoutubeService = GetYouTubeService()
Dim SourceVideo As String = "C:TempMediaWildlife.wmv"
Dim Meta As New Video
Meta.Snippet = New VideoSnippet
Meta.Snippet.Title = "Test Wildlife Video"
Meta.Snippet.Description = "This is a test video only"
Meta.Snippet.CategoryId = "Animals"
Meta.Snippet.Tags = New List(Of String)
Meta.Snippet.Tags.Add("Test")
Meta.Status = New VideoStatus
Meta.Status.PrivacyStatus = "unlisted"
Using fs As New FileStream(SourceVideo, FileMode.Open, FileAccess.Read, FileShare.Inheritable)
Dim UploadRequest As VideosResource.InsertMediaUpload = Service.Videos.Insert(Meta, "snippet,statistics,status", fs, "application/octet-stream")
UploadRequest.Upload()
Dim Uploaded = UploadRequest.ResponseBody
End Using
经过思考,这是在SendChunk 中抛出500内部服务器错误
System.Net.WebException was unhandled HResult=-2146233079 Message=The remote server returned an error: (500) Internal Server Error. Source=System StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at Google.Apis.Upload.ResumableUpload`1.SendChunk(Stream stream, Uri uri, Int64 position) in c:code.google.comgoogle-api-dotnet-clientdefaultToolsBuildReleasebinDebug12-20-2012defaultSrcGoogleApisApisUploadResumableUpload.cs:line 452
at Google.Apis.Upload.ResumableUpload`1.Upload() in c:code.google.comgoogle-api-dotnet-clientdefaultToolsBuildReleasebinDebug12-20-2012defaultSrcGoogleApisApisUploadResumableUpload.cs:line 315
at QUICTools.Workflow.Social.YouTube.QuicYouTube.TestUpload() in C:Userskenny.munro.ZAZADocumentsVisual Studio 2010ProjectsQUIC_V2.0QUICTools.Workflow.Social.YouTubeQuicYouTube.vb:line 37
at QLTest.Form1.SimpleButton1_Click(Object sender, EventArgs e) in C:Userskenny.munro.ZAZADocumentsVisual Studio 2010ProjectsQUIC_V2.0QLTestForm1.vb:line 4
at System.Windows.Forms.Control.OnClick(EventArgs e)
at DevExpress.XtraEditors.BaseButton.OnClick(EventArgs e)
at DevExpress.XtraEditors.BaseButton.OnKeyUp(KeyEventArgs e)
at System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)
at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
at System.Windows.Forms.Control.WmKeyChar(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at DevExpress.Utils.Controls.ControlBase.WndProc(Message& m)
at DevExpress.XtraEditors.BaseControl.WndProc(Message& msg)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at QLTest.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart() InnerException:
我不得不承认我现在被难住了。有人有使用V3 dotnet API上传到YouTube的工作示例吗?或者有可能出错的建议吗?
更新
我一直在使用Fiddler对此进行更多的分析。首先,我设置添加了一行来设置chunkSize=10000。我现在可以看到大量的块被上传得很好,并返回308个响应代码。错误由最后的部分块返回:
PUT /upload/youtube/v3/videos?uploadType=resumable&alt=json&part=snippet%2Cstatus&upload_id=AEnB2UqVVIYV1YyYk27JhhFj_U2WzbK0_ghq0QIRsO1dB1caaMrazd-wlULFZVxvM_pHDZFJkVmUJbYw4oVicI2rfJujdXy4ZQ HTTP/1.1
Content-Range: bytes 26250000-26255829/26255830
Host: www.googleapis.com
Content-Length: 5830
500 Internal Server Error (application/json)
不太确定这怎么可能是我做错了什么,但如果有人能提供一些意见/验证,我将不胜感激。
为了完整起见,这里是初始的插入命令——同样,对我来说一切都很好:
POST /upload/youtube/v3/videos?uploadType=resumable&alt=json&part=snippet%2Cstatus HTTP/1.1
X-Upload-Content-Type: video/x-ms-wmv
X-Upload-Content-Length: 26255830
Authorization: Bearer ya29.AHES6ZTQsUz4SI-jOnCO8kL3hg_L...
Content-Type: application/json
Host: www.googleapis.com
Content-Length: 168
Connection: Keep-Alive
{"snippet":{"categoryId":"Entertainment","description":"This is a test video only","tags":["Test"],"title":"Test Wildlife Video"},"status":{"privacyStatus":"unlisted"}}
HTTP/1.1 200 OK
Server: HTTP Upload Server Built on Feb 6 2013 15:53:54 (1360194834)
Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&alt=json&part=snippet%2Cstatus&upload_id=AEnB2UqVVIYV1YyYk27JhhFj_U2WzbK0_ghq0QIRsO1dB1caaMrazd-wlULFZVxvM_pHDZFJkVmUJbYw4oVicI2rfJujdXy4ZQ
Date: Tue, 19 Feb 2013 13:58:18 GMT
Pragma: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 0
Content-Type: text/html; charset=UTF-8
CategoryId是一个数字。您可以使用此示例下载所有有效类别的ID(编号)和标题的列表。本例将ID和Title放入一个自定义类对象中,并将每个类对象添加为ComboBox控件中的一个项。
OAUth2Credential = Nothing
Try
GetGredentials.Wait()
objYouTubeService = New YouTubeService(New BaseClientService.Initializer() With { _
.HttpClientInitializer = OAUth2Credential, _
.ApplicationName = Assembly.GetExecutingAssembly().GetName().Name})
Catch ex As Exception
MsgBox(ex.Message)
End
End Try
Dim objCategories As VideoCategoryListResponse = Nothing
Try
Dim objRequest As VideoCategoriesResource.ListRequest = New VideoCategoriesResource.ListRequest(objYouTubeService, "id,snippet")
objRequest.Hl = "en_US"
objRequest.RegionCode = "US"
objCategories = objRequest.Execute
Catch ex As Exception
MsgBox(ex.Message)
End Try
cmbCategory.DisplayMember = "Title"
cmbCategory.ValueMember = "Id"
For Each obj As VideoCategory In objCategories.Items
cmbCategory.Items.Add(New CategoryClass(obj.Id, obj.Snippet.Title))
If obj.Snippet.Title.Contains("News") Then
intDefaultCategoryIndex = cmbCategory.Items.Count - 1
End If
Next
cmbCategory.SelectedIndex = intDefaultCategoryIndex
...
以下是我如何填写OAuth2Credential。
Private Async Function GetGredentials() As Task
Try
'
' ClientId and ClientSecret are found in your client_secret_*****.apps.googleusercontent.com.json file downloaded from
' the Google Developers Console ( https://console.developers.google.com).
' This sample shows the ClientID and ClientSecret in the source code.
' Other samples in the sample library show how to read the Client Secrets from the ' client_secret_*****.apps.googleusercontent.com.json file.
'
OAUth2Credential = Await GoogleWebAuthorizationBroker.AuthorizeAsync( _
New ClientSecrets With {.ClientId = "Your Client ID goes here ..............................................", _
.ClientSecret = "Your Client Secret goes here."}, _
{YouTubeService.Scope.Youtube}, "user", CancellationToken.None)
If OAUth2Credential IsNot Nothing Then
If OAUth2Credential.Token IsNot Nothing Then
AddToLog(String.Concat("Token Issued: ", OAUth2Credential.Token.Issued))
End If
End If
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Google Authorization")
End
End Try
End Function
这就是我的自定义类的样子:
Friend Class CategoryClass
Dim m_Id As String
Dim m_Title As String
Sub New(ByVal Id As String, ByVal Title As String)
m_Id = Id
m_Title = Title
End Sub
Property ID As String
Get
ID = m_Id
End Get
Set(value As String)
m_Id = value
End Set
End Property
Property Title As String
Get
Title = m_Title
End Get
Set(value As String)
m_Title = value
End Set
End Property
End Class
既然你是按块上传的,为什么不捕捉进度和响应接收到的事件,这样你就可以获得更多关于正在发生的事情的信息。以下是您的操作方法:
UploadRequest.ChunkSize = 10000;
UploadRequest.ProgressChanged += UploadRequest_ProgressChanged;
UploadRequest.ResponseReceived += UploadRequest_ResponseReceived;
Sub UploadRequest_ProgressChanged(obj As Google.Apis.Upload.IUploadProgress)
' check if the upload has been completed
If obj.Status = Google.Apis.Upload.UploadStatus.Completed Then
' do something here
End If
' or check the status and handle it appropriately
' see "Google.Apis.Upload.UploadStatus" for possible status returned
' or check the details of the exception here
If obj.Exception IsNot Nothing Then
Console.WriteLine(obj.Exception.Message)
End If
End Sub
Sub UploadRequest_ResponseReceived(Google.Apis.Youtube.v3.Data.Video obj)
' your video object will be available here once the upload is done
End Sub
注意:我用C#写了这个,并用一个网站将其转换为VB,所以可能会有一些语法错误,我相信你知道如何修复它。