YouTube的C#API V3,你如何恢复中断的上传? [英] YouTube C# API V3, how do you resume an interrupted upload?

查看:470
本文介绍了YouTube的C#API V3,你如何恢复中断的上传?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不能工作,如何恢复在C#中的YouTube API的V3中断的上传。



我现有的代码使用V1和工作正常,但我切换到V3。



如果我叫UploadAsync()不改变任何东西,它从一开始就开始。使用招,我可以看到这里给出是没有遵循协议,并上传重启



我试过设置为每V1流内的位置,但没有可用的ResumeAsync()方法。



Python的例子使用NextChunk但SendNextChunk方法得到保护,并在C#中无法使用。



在下面的代码中,无论是UploadVideo()和resume()工作很好,如果我离开他们完成,但是整个视频被上传,而不是仅仅的其余部分。



如何恢复使用google.apis.youtube.v3中断上传?



下面是C#代码到目前为止,我都试过了。



<预类=郎-C#prettyprint,覆盖> 私人ResumableUpload<视频> UploadVideo(
YouTubeService youTubeService,视频录像,流流,UserCredential userCredentials)
{
VAR resumableUpload = youTubeService.Videos.Insert(视频,
片段,地位,contentDetails流,视频/ *);
resumableUpload.OauthToken = userCredentials.Token.AccessToken;
resumableUpload.C​​hunkSize = 256 * 1024;
resumableUpload.ProgressChanged + = resumableUpload_ProgressChanged;
resumableUpload.ResponseReceived + = resumableUpload_ResponseReceived;
resumableUpload.UploadAsync();
返回resumableUpload;
}

私人无效简历(ResumableUpload<视频> resumableUpload)
{
//我试图寻找像V1,但它不工作,
/ /如果(resumableUpload.C​​ontentStream.CanSeek)
// resumableUpload.C​​ontentStream.Seek(resumableUpload.C​​ontentStream.Position,SeekOrigin.Begin);

resumableUpload.UploadAsync(); //< ----这将重新启动上传
}

无效resumableUpload_ResponseReceived(视频OBJ)
{
的Debug.WriteLine(视频状态:{0 },obj.Status.UploadStatus);
}

无效resumableUpload_ProgressChanged(IUploadProgress OBJ)
{
的Debug.WriteLine(位置:{0}(resumableUploadTest == NULL)?0:resumableUploadTest .ContentStream.Position);
的Debug.WriteLine(状态:{0},obj.Status);
的Debug.WriteLine(发送的字节数:{0},obj.BytesSent);
}

私人无效button2_Click(对象发件人,EventArgs五)
{
简历(resumableUploadTest);
}



任何解决方案/建议/演示或以google.apis的链接。 !youtube.v3源代码将是非常有益的。



在此先感谢



编辑:新的信息



我仍然在做这个,我相信API根本没有完成。如果不是这样,我想的东西很简单。



我仍然无法找到google.apis.youtube.v3的源代码,所以我下载了最新的谷歌-API-DOTNET客户的源代码。这包含通过YouTube的API使用的ResumableUpload类。



我设法通过跳过代码前四行在UploadAsync()方法成功继续上传。我删除前四行的初始化代码创建了一个名为ResumeAsync())的新方法,UploadAsync复印件(。一切工作,并上传从它在哪里,并完成恢复。



我宁愿不API中更改代码,所以如果有人知道我应该如何利用这一点,让我知道。



我会继续刻苦,看看我能做得出来。



这,是原UploadAsync()方法和我的ResumeAsync()破解



<预类=郎-C#prettyprint-覆盖> 公共异步任务< IUploadProgress> ; UploadAsync(的CancellationToken的CancellationToken)
{

{
BytesServerReceived = 0;
的UpdateProgress(新ResumableUploadProgress(UploadStatus.Starting,0)); //检查
如果流的长度是已知的。
StreamLength = ContentStream.CanSeek? ContentStream.Length:UnknownSize;
UploadUri =等待InitializeUpload(的CancellationToken).ConfigureAwait(假);

Logger.Debug(MediaUpload [{0}] - 开始上传...,UploadUri);使用

(VAR回调=新ServerErrorCallback(本))
{
,而(!等待SendNextChunkAsync(ContentStream,的CancellationToken).ConfigureAwait(假))
$ { b $ b的UpdateProgress(新ResumableUploadProgress(UploadStatus.Uploading,BytesServerReceived));
}
的UpdateProgress(新ResumableUploadProgress(UploadStatus.Completed,BytesServerReceived));
}
}
赶上(TaskCanceledException前)
{
Logger.Error(例如,MediaUpload [{0}] - 任务被取消,UploadUri);
的UpdateProgress(新ResumableUploadProgress(例如,BytesServerReceived));
罚球前;
}
赶上(异常前)
{
Logger.Error(例如, - ,UploadUriMediaUpload [{0}]上传时发生媒体异常);
的UpdateProgress(新ResumableUploadProgress(例如,BytesServerReceived));
}

返回进展情况;
}

公共异步任务< IUploadProgress> ResumeAsync(的CancellationToken的CancellationToken)
{

{
使用(VAR回调=新ServerErrorCallback(本))
{
,而(!等待SendNextChunkAsync( ContentStream,的CancellationToken).ConfigureAwait(假))
{
的UpdateProgress(新ResumableUploadProgress(UploadStatus.Uploading,BytesServerReceived));
}
的UpdateProgress(新ResumableUploadProgress(UploadStatus.Completed,BytesServerReceived));
}
}
赶上(TaskCanceledException前)
{
的UpdateProgress(新ResumableUploadProgress(例如,BytesServerReceived));
罚球前;
}
赶上(异常前)
{
的UpdateProgress(新ResumableUploadProgress(例如,BytesServerReceived));
}

返回进展情况;
}



以上是的提琴手记录显示上传断点续传。


解决方案

我已经成功地得到这个使用反射来工作,避免了需要在所有修改API。为了完整起见,我会记录下过程,但不建议。在可恢复上传对象设置私人财产是不是一个好主意。



当您resumeable上传对象已重新启动应用程序或重新启动时被破坏了,你仍然可以继续上传使用版本1.8.0.960-RC的 Google.Apis.YouTube.v3 。客户端库

 私有静态无效SetPrivateProperty< T>(obj对象,字符串propertyName的,对象的值)
{
变种的PropertyInfo = typeof运算(T).GetProperty(propertyName的,BindingFlags.NonPublic可| BindingFlags.Instance);
如果(的PropertyInfo == NULL)回报;
propertyInfo.SetValue(OBJ,值null);
}

私有静态对象GetPrivateProperty< T>(obj对象,字符串propertyName的)
{
如果(OBJ == NULL)返回NULL;
变种的PropertyInfo = typeof运算(T).GetProperty(propertyName的,BindingFlags.NonPublic可| BindingFlags.Instance);
返回的PropertyInfo == NULL?空:propertyInfo.GetValue(OBJ,NULL);
}

您需要ProgressChanged事件期间保存UploadUri。

  Upload.ResumeUri = GetPrivateProperty< ResumableUpload<视频>>(InsertMediaUploadUploadUri)作为开放的; 

您需要在调用ResumeAsync之前设置UploadUri和StreamLength。

 私人常量长UnknownSize = -1; 
SetPrivateProperty< ResumableUpload<视频>>(InsertMediaUpload,UploadUri,Upload.ResumeUri);
SetPrivateProperty< ResumableUpload<视频>>(InsertMediaUpload,StreamLength,fileStream.CanSeek fileStream.Length:Constants.UnknownSize);
=任务InsertMediaUpload.ResumeAsync(CancellationTokenSource.Token);


I can't work out how to resume an interrupted upload in V3 of the C# YouTube API.

My existing code uses V1 and works fine but I'm switching to V3.

If I call UploadAsync() without changing anything, it starts from the beginning. Using Fiddler, I can see the protocol given here is not followed and the upload restarts.

I've tried setting the position within the stream as per V1 but there is no ResumeAsync() method available.

The Python example uses NextChunk but the SendNextChunk method is protected and not available in C#.

In the code below, both UploadVideo() and Resume() work fine if I leave them to completion but the entire video is uploaded instead of just the remaining parts.

How do I resume an interrupted upload using google.apis.youtube.v3?

Here is the C# code I have tried so far.

private ResumableUpload<Video> UploadVideo(
    YouTubeService youTubeService, Video video, Stream stream, UserCredential userCredentials)
{
    var resumableUpload = youTubeService.Videos.Insert(video, 
        "snippet,status,contentDetails", stream, "video/*");
    resumableUpload.OauthToken = userCredentials.Token.AccessToken;
    resumableUpload.ChunkSize = 256 * 1024;
    resumableUpload.ProgressChanged += resumableUpload_ProgressChanged;
    resumableUpload.ResponseReceived += resumableUpload_ResponseReceived;                   
    resumableUpload.UploadAsync();
    return resumableUpload;
}

private void Resume(ResumableUpload<Video> resumableUpload)
{   
    //I tried seeking like V1 but it doesn't work
    //if (resumableUpload.ContentStream.CanSeek)
    //  resumableUpload.ContentStream.Seek(resumableUpload.ContentStream.Position, SeekOrigin.Begin);

    resumableUpload.UploadAsync(); // <----This restarts the upload                             
}

void resumableUpload_ResponseReceived(Video obj)
{                   
    Debug.WriteLine("Video status: {0}", obj.Status.UploadStatus);                      
}

void resumableUpload_ProgressChanged(IUploadProgress obj)
{
    Debug.WriteLine("Position: {0}", (resumableUploadTest == null) ? 0 : resumableUploadTest.ContentStream.Position);   
    Debug.WriteLine("Status: {0}", obj.Status);
    Debug.WriteLine("Bytes sent: {0}", obj.BytesSent);
}

private void button2_Click(object sender, EventArgs e)
{
    Resume(resumableUploadTest);
}

Any solution/suggestion/demo or a link to the "google.apis.youtube.v3" source code will be very helpful.

Thanks in Advance !

EDIT: New information

I'm still working on this and I believe the API simply isn't finished. Either that or I'm missing something simple.

I still can't find the "google.apis.youtube.v3" source code so I downloaded the latest "google-api-dotnet-client" source code. This contains the ResumableUpload class used by the YouTube API.

I managed to successfully continue an upload by skipping the first four lines of code in the UploadAsync() method. I created a new method called ResumeAsync(), a copy of UploadAsync() with the first four lines of initialization code removed. Everything worked and the upload resumed from where it was and completed.

I'd rather not be changing code in the API so if anyone knows how I should be using this, let me know.

I'll keep plugging away and see if I can work it out.

This is the original UploadAsync() method and my ResumeAsync() hack.

public async Task<IUploadProgress> UploadAsync(CancellationToken cancellationToken)
{
    try
    {
        BytesServerReceived = 0;
        UpdateProgress(new ResumableUploadProgress(UploadStatus.Starting, 0));
        // Check if the stream length is known.
        StreamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize;
        UploadUri = await InitializeUpload(cancellationToken).ConfigureAwait(false);

        Logger.Debug("MediaUpload[{0}] - Start uploading...", UploadUri);

        using (var callback = new ServerErrorCallback(this))
        {
            while (!await SendNextChunkAsync(ContentStream, cancellationToken).ConfigureAwait(false))
            {
                UpdateProgress(new ResumableUploadProgress(UploadStatus.Uploading, BytesServerReceived));
            }
            UpdateProgress(new ResumableUploadProgress(UploadStatus.Completed, BytesServerReceived));
        }
    }
    catch (TaskCanceledException ex)
    {
        Logger.Error(ex, "MediaUpload[{0}] - Task was canceled", UploadUri);
        UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived));
        throw ex;
    }
    catch (Exception ex)
    {
        Logger.Error(ex, "MediaUpload[{0}] - Exception occurred while uploading media", UploadUri);
        UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived));
    }

    return Progress;
}

public async Task<IUploadProgress> ResumeAsync(CancellationToken cancellationToken)
{
    try
    {
        using (var callback = new ServerErrorCallback(this))
        {
            while (!await SendNextChunkAsync(ContentStream, cancellationToken).ConfigureAwait(false))
            {
                UpdateProgress(new ResumableUploadProgress(UploadStatus.Uploading, BytesServerReceived));
            }
            UpdateProgress(new ResumableUploadProgress(UploadStatus.Completed, BytesServerReceived));
        }
    }
    catch (TaskCanceledException ex)
    {                       
        UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived));
        throw ex;
    }
    catch (Exception ex)
    {                       
        UpdateProgress(new ResumableUploadProgress(ex, BytesServerReceived));
    }

    return Progress;
}

These are the Fiddler records showing the upload resuming.

解决方案

I've managed to get this to work using reflection and avoided the need to modify the API at all. For completeness, I'll document the process but it isn't recommended. Setting private properties in the resumable upload object is not a great idea.

When your resumeable upload object has been destroyed after an application restart or reboot, you can still resume an upload using version "1.8.0.960-rc" of the Google.Apis.YouTube.v3 Client Library.

private static void SetPrivateProperty<T>(Object obj, string propertyName, object value)
{
    var propertyInfo = typeof(T).GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);
    if (propertyInfo == null) return;
    propertyInfo.SetValue(obj, value, null);
}

private static object GetPrivateProperty<T>(Object obj, string propertyName)
{
    if (obj == null) return null;
    var propertyInfo = typeof(T).GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance);
    return propertyInfo == null ? null : propertyInfo.GetValue(obj, null);
}

You need to save the UploadUri during the ProgressChanged event.

Upload.ResumeUri = GetPrivateProperty<ResumableUpload<Video>>(InsertMediaUpload, "UploadUri") as Uri;

You need to set the UploadUri and StreamLength before calling ResumeAsync.

private const long UnknownSize = -1;
SetPrivateProperty<ResumableUpload<Video>>(InsertMediaUpload, "UploadUri", Upload.ResumeUri);
SetPrivateProperty<ResumableUpload<Video>>(InsertMediaUpload, "StreamLength", fileStream.CanSeek ? fileStream.Length : Constants.UnknownSize);
Task = InsertMediaUpload.ResumeAsync(CancellationTokenSource.Token);

这篇关于YouTube的C#API V3,你如何恢复中断的上传?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆