基于ASP.NET的Google API网站端YouTube上传进度显示问题求助
Hey Gary, 当然可以通过异步调用来实现上传进度、完成状态和错误信息的页面展示!你用的那个可恢复上传示例其实已经内置了捕获进度与状态的钩子,只是没做页面呈现而已。我结合你的场景(用户在网站独立登录,但视频上传至你们的企业YouTube账号),给你拆解具体的解决方案:
一、利用异步上传的事件钩子捕获状态
那个ResumableUpload异步实例自带ProgressChanged和Completed事件,你只需要订阅这两个事件,就能实时获取上传数据,再同步到前端页面:
1. 订阅事件并发起异步上传(VB代码)
' 创建ResumableUpload实例(按你现有代码初始化) Dim upload As New ResumableUpload(...) ' 订阅进度变化事件 AddHandler upload.ProgressChanged, AddressOf Upload_ProgressChanged ' 订阅上传完成/错误事件 AddHandler upload.Completed, AddressOf Upload_Completed ' 启动异步上传 Await upload.UploadAsync()
2. 实现事件处理方法(更新页面UI)
注意Web环境下更新UI需要通过前端脚本注入(以ASP.NET WebForms为例):
Private Sub Upload_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) ' 计算上传进度百分比 Dim progressPercent As Integer = CInt((e.BytesSent / e.TotalBytesToSend) * 100) ' 调用前端JS更新进度条 ScriptManager.RegisterStartupScript(Me, Me.GetType(), "updateProgress", $"updateProgress({progressPercent});", True) End Sub Private Sub Upload_Completed(sender As Object, e As Google.Apis.Upload.ResumableUploadCompletedEventArgs(Of Video)) If e.Error IsNot Nothing Then ' 上传出错,展示错误信息 ScriptManager.RegisterStartupScript(Me, Me.GetType(), "uploadError", $"showError('{HttpUtility.JavaScriptStringEncode(e.Error.Message)}');", True) Else ' 上传成功,展示完成状态 ScriptManager.RegisterStartupScript(Me, Me.GetType(), "uploadSuccess", "showSuccess('视频上传完成!');", True) End If End Sub
3. 前端配套JS(页面中添加)
// 更新进度条 function updateProgress(percentage) { const progressBar = document.getElementById('uploadProgressBar'); const progressText = document.getElementById('progressText'); progressBar.style.width = percentage + '%'; progressText.textContent = `${percentage}% 已完成`; } // 展示错误信息 function showError(message) { const statusArea = document.getElementById('statusMessage'); statusArea.innerHTML = `<span style="color: #dc3545;">上传失败:${message}</span>`; } // 展示成功状态 function showSuccess(message) { const statusArea = document.getElementById('statusMessage'); statusArea.innerHTML = `<span style="color: #28a745;">${message}</span>`; }
二、针对你的OAuth2场景的关键优化
你提到用户有独立网站账号,但视频要传到你们的企业YouTube账号,这里要注意:
不要让用户授权你们的YouTube账号(会导致权限泄露),应该改用**服务账号(Service Account)**实现服务器端上传:
- 在Google Cloud Console创建服务账号,授予YouTube Data API的操作权限;
- 在YouTube Studio里把该服务账号添加为你们企业频道的管理员;
- 服务器端用服务账号凭据完成上传,用户只需要在你们网站登录,无需授权Google账号。
这种方式下,上传逻辑完全在服务器端执行,你依然可以通过上述事件钩子捕获状态并同步到前端。
三、如果Web环境下异步事件失效的备选方案
如果因为Web页面生命周期问题,异步事件无法触发UI更新,可以改用后台任务+前端轮询的方式:
- 发起上传时,给每个任务分配唯一ID,把进度、完成状态、错误信息存在Session或数据库中;
- 前端用JS定时(比如每秒)发送AJAX请求到服务器,获取该任务的最新状态;
- 服务器端返回状态后,前端更新UI。
举个简化的服务器端API示例:
<WebMethod> Public Shared Function GetUploadStatus(taskId As String) As UploadStatus ' 从Session中获取任务状态(也可存在数据库) Return DirectCast(HttpContext.Current.Session($"UploadTask_{taskId}"), UploadStatus) End Function ' 状态实体类 Public Class UploadStatus Public Property ProgressPercent As Integer Public Property IsCompleted As Boolean Public Property ErrorMsg As String End Class
前端轮询JS:
function startPolling(taskId) { const pollInterval = setInterval(() => { $.ajax({ url: 'UploadPage.aspx/GetUploadStatus', type: 'POST', contentType: 'application/json; charset=utf-8', data: JSON.stringify({ taskId: taskId }), success: function(res) { const status = res.d; updateProgress(status.ProgressPercent); if (status.IsCompleted) { clearInterval(pollInterval); status.ErrorMsg ? showError(status.ErrorMsg) : showSuccess('上传完成!'); } } }); }, 1000); }
这种方式兼容性更强,能适配大部分Web框架的生命周期限制。
内容的提问来源于stack exchange,提问作者Gary Brownjohn
相关产品推荐
相关产品推荐

