我不知道如何在 C# YouTube API 的 V3 中恢复中断的上传。
我现有的代码使用 V1 并且工作正常,但我正在切换到 V3。
如果我在不做任何更改的情况下调用 UploadAsync(),它会从头开始。使用 Fiddler,我可以看到 protocol given here未遵循并重新开始上传。
我已尝试按照 V1 设置流中的位置,但没有可用的 ResumeAsync() 方法。
Python 示例使用 NextChunk,但 SendNextChunk 方法 protected 且在 C# 中不可用。
在下面的代码中,如果我让它们完成,则 UploadVideo() 和 Resume() 都可以正常工作,但会上传整个视频,而不仅仅是其余部分。
如何使用 google.apis.youtube.v3 恢复中断的上传?
这是我到目前为止尝试过的 C# 代码。
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);
}
任何解决方案/建议/演示或指向“google.apis.youtube.v3”源代码的链接都将非常有帮助。
提前致谢!
编辑:新信息
我仍在努力,我相信 API 还没有完成。要么,要么我遗漏了一些简单的东西。
我仍然找不到“google.apis.youtube.v3”源代码,所以我下载了最新的“google-api-dotnet-client”源代码。这包含 YouTube API 使用的 ResumableUpload 类。
我通过跳过 UploadAsync() 方法中的前四行代码成功地继续上传。我创建了一个名为 ResumeAsync() 的新方法,它是 UploadAsync() 的一个副本,删除了前四行初始化代码。一切正常,上传从原来的位置恢复并完成。
我不想更改 API 中的代码,所以如果有人知道我应该如何使用它,请告诉我。
我会继续加类,看看能不能解决。
这是原始的 UploadAsync() 方法和我的 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;
}
这些是 Fiddler records显示正在恢复上传。
最佳答案
经过深思熟虑,我决定修改 API 代码。我的解决方案保持向后兼容性。
我在下面记录了我的更改,但我不建议使用它们。
在“Google.Apis.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 属性。这两个属性可以在原始上传期间保存。视频详情和内容流可以正常配置。
即使在重新启动应用程序或重新启动后,这些少量更改也可以恢复上传。我不确定上传过期还有多久,但我会在对真实应用程序进行更多测试后报告。
为了完整起见,这是我一直在使用的测试代码,在上传过程中多次重启应用程序后,它会愉快地恢复中断的上传。恢复和重新启动之间的唯一区别是设置 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();
我希望这对某人有所帮助。我花了比预期更长的时间来解决这个问题,我仍然希望我错过了一些简单的事情。我花了很长时间试图添加我自己的错误处理程序,但 API 会为您完成所有这些工作。 API 确实可以从轻微的短时间中断中恢复,但不能从应用程序重新启动、重新启动或长时间中断中恢复。
干杯。米克。
关于c# - YouTube C# API V3,如何恢复中断的上传?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21321878/