YouTube C#API V3,如何恢复中断的上传?

YouTube C#API V3,如何恢复中断的上传?,c#,upload,google-api-dotnet-client,youtube.net-api,resume-upload,C#,Upload,Google Api Dotnet Client,Youtube.net Api,Resume Upload,我不知道如何在C#YouTube API的V3中恢复中断的上传 我现有的代码使用V1,工作正常,但我正在切换到V3 如果我调用UploadAsync()而不做任何更改,它将从头开始。使用Fiddler,我可以看到没有遵循,上传重新启动 我尝试按照V1设置流中的位置,但没有可用的ResumeAync()方法 Python示例使用NextChunk,但SendNextChunk方法受保护,在C#中不可用 在下面的代码中,如果我让UploadVideo()和Resume()完成,它们都可以正常工作,但

我不知道如何在C#YouTube API的V3中恢复中断的上传

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

如果我调用UploadAsync()而不做任何更改,它将从头开始。使用Fiddler,我可以看到没有遵循,上传重新启动

我尝试按照V1设置流中的位置,但没有可用的ResumeAync()方法

Python示例使用NextChunk,但SendNextChunk方法受保护,在C#中不可用

在下面的代码中,如果我让UploadVideo()和Resume()完成,它们都可以正常工作,但是整个视频都会被上传,而不仅仅是剩下的部分

如何使用google.api.youtube.v3恢复中断的上传

这是我迄今为止尝试过的C代码

私人可恢复上传视频(
YouTube服务YouTube服务、视频、流、用户凭据(用户凭据)
{
var resumableUpload=youTubeService.Videos.Insert(视频、,
“片段、状态、内容详细信息”,流,“视频/*”;
resumableUpload.OauthToken=userCredentials.Token.AccessToken;
resumableUpload.ChunkSize=256*1024;
resumableUpload.ProgressChanged+=resumableUpload\u ProgressChanged;
resumableUpload.ResponseReceived+=resumableUpload\u ResponseReceived;
resumableUpload.UploadAsync();
返回可恢复载荷;
}
私人无效恢复(ResumableUpload ResumableUpload)
{   
//我试着像V1一样寻找,但它不起作用
//if(resumableUpload.ContentStream.CanSeek)
//resumableUpload.ContentStream.Seek(resumableUpload.ContentStream.Position,SeekOrigin.Begin);

resumableUpload.UploadAsync();//经过深思熟虑,我决定修改API代码。我的解决方案保持向后兼容性

我已经在下面记录了我的更改,但我不建议使用它们

在“Google.api.Upload”中ResumableUpload类的UploadAsync()方法中,我替换了这段代码

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);
使用此代码

UpdateProgress(new ResumableUploadProgress(
    BytesServerReceived == 0 ? UploadStatus.Starting : UploadStatus.Resuming, BytesServerReceived));
StreamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize;
if (UploadUri == null) UploadUri = await InitializeUpload(cancellationToken).ConfigureAwait(false);
我还公开了UploadUri和BytesServerReceived属性。这允许在ResumableUpload对象被销毁或应用程序重新启动后继续上载

您只需按照正常方式重新创建ResumableUpload,设置这两个字段并调用UploadAsync()以恢复上载。这两个字段都需要在原始上载过程中保存

public Uri UploadUri { get; set; }
public long BytesServerReceived { get; set; }
我还在IUploadProgress类的UploadStatus枚举中添加了“Resuming”

public enum UploadStatus
{
    /// <summary>
    /// The upload has not started.
    /// </summary>
    NotStarted,

    /// <summary>
    /// The upload is initializing.
    /// </summary>
    Starting,

    /// <summary>
    /// Data is being uploaded.
    /// </summary>
    Uploading,

    /// <summary>
    /// Upload is being resumed.
    /// </summary>
    Resuming,

    /// <summary>
    /// The upload completed successfully.
    /// </summary>
    Completed,

    /// <summary>
    /// The upload failed.
    /// </summary>
    Failed
};
公共枚举上载状态
{
/// 
///上载尚未开始。
/// 
没有开始,
/// 
///上载正在初始化。
/// 
启动,
/// 
///正在上载数据。
/// 
上传,
/// 
///正在恢复上载。
/// 
恢复,,
/// 
///上载已成功完成。
/// 
完整的,
/// 
///上载失败。
/// 
失败
};
启动上载时没有任何更改

如果ResumableUpload项目和流未被销毁,请再次调用UploadAsync()以恢复中断的上载

如果已销毁,则创建新对象并设置UploadUri和BytesServerReceived属性。这两个属性可在原始上载期间保存。视频详细信息和内容流可按正常配置

这几项更改允许在重新启动应用程序或重新启动后恢复上载。我不确定上载将在多长时间后过期,但我将在对实际应用程序进行更多测试后报告

public Uri UploadUri { get; private set; }
为了完整起见,这是我一直在使用的测试代码,在上载过程中多次重新启动应用程序后,它会愉快地恢复中断的上载。恢复和重新启动之间的唯一区别是设置UploadUri和BytesServerReceived属性

resumableUploadTest = youTubeService.Videos.Insert(video, "snippet,status,contentDetails", fileStream, "video/*");
if (resume)
{
    resumableUploadTest.UploadUri = Settings.Default.UploadUri;
    resumableUploadTest.BytesServerReceived = Settings.Default.BytesServerReceived;                 
}                                               
resumableUploadTest.ChunkSize = ResumableUpload<Video>.MinimumChunkSize;
resumableUploadTest.ProgressChanged += resumableUpload_ProgressChanged;
resumableUploadTest.UploadAsync();
resumableUploadTest=youTubeService.Videos.Insert(视频,“片段、状态、内容详细信息”,文件流,“视频/*”);
如果(恢复)
{
resumableUploadTest.UploadUri=Settings.Default.UploadUri;
resumableUploadTest.BytesServerReceived=Settings.Default.BytesServerReceived;
}                                               
resumableUploadTest.ChunkSize=ResumableUpload.MinimumChunkSize;
resumableUpload test.ProgressChanged+=resumableUpload\u ProgressChanged;
resumableUploadTest.UploadAsync();
我希望这对某些人有所帮助。我花了比预期长得多的时间来解决这个问题,我仍然希望我错过了一些简单的事情。我花了很长时间试图添加自己的错误处理程序,但API为您完成了所有这一切。API不会从轻微的短暂故障中恢复,但不会从应用程序重新启动、重新启动或长时间停机中恢复


Cheers.Mick.

此问题已在的“1.8.0.960-rc”版本中得到解决

他们添加了一个名为ResumeAsync的新方法,效果很好。我希望我知道他们正在使用它

我需要解决的一个小问题是在重新启动应用程序或重新启动后恢复上载。当前api不允许这样做,但两个小更改解决了该问题

我为ResumeAync方法添加了一个新签名,该方法接受并设置原始的UploadUri。需要初始化StreamLength属性以避免溢出错误

public Task<IUploadProgress> ResumeAsync(Uri uploadUri, CancellationToken cancellationToken)
{
    UploadUri = uploadUri;
    StreamLength = ContentStream.CanSeek ? ContentStream.Length : UnknownSize;
    return ResumeAsync(cancellationToken);
}

我使用反射成功地实现了这一点,并且完全避免了修改API的需要。为了完整性,我将记录此过程,但不建议这样做。在可恢复上载对象中设置私有属性不是一个好主意

当应用程序重新启动或重新启动后,可恢复上载对象已被销毁时,您仍然可以使用的“1.8.0.960-rc”版本恢复上载

private static void SetPrivateProperty(对象obj,字符串propertyName,对象值)
{
var propertyInfo=
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);
}
Upload.ResumeUri = GetPrivateProperty<ResumableUpload<Video>>(InsertMediaUpload, "UploadUri") as Uri;
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);