我使用服务帐户上传到Google云端存储。我需要能够在WPF UI中显示上传的进度。现在,每当我尝试更新ProgressBar.Value时,它都不起作用,但是当我在控制台中编写bytesSent时,我可以看到进度。
public async Task<bool> UploadToGoogleCloudStorage(string bucketName, string token, string filePath, string contentType)
{
var newObject = new Google.Apis.Storage.v1.Data.Object()
{
Bucket = bucketName,
Name = System.IO.Path.GetFileNameWithoutExtension(filePath)
};
var service = new Google.Apis.Storage.v1.StorageService();
try
{
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
var uploadRequest = new ObjectsResource.InsertMediaUpload(service, newObject, bucketName, fileStream, contentType);
uploadRequest.OauthToken = token;
ProgressBar.Maximum = fileStream.Length;
uploadRequest.ProgressChanged += UploadProgress;
uploadRequest.ChunkSize = (256 * 1024);
await uploadRequest.UploadAsync().ConfigureAwait(false);
service.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw ex;
}
return true;
}
private void UploadProgress(IUploadProgress progress)
{
switch (progress.Status)
{
case UploadStatus.Starting:
ProgressBar.Minimum = 0;
ProgressBar.Value = 0;
break;
case UploadStatus.Completed:
System.Windows.MessageBox.Show("Upload completed!");
break;
case UploadStatus.Uploading:
//Console.WriteLine(progress.BytesSent); -> This is working if I don't call the method below.
UpdateProgressBar(progress.BytesSent);
break;
case UploadStatus.Failed:
Console.WriteLine("Upload failed "
+ Environment.NewLine
+ progress.Exception.Message
+ Environment.NewLine
+ progress.Exception.StackTrace
+ Environment.NewLine
+ progress.Exception.Source
+ Environment.NewLine
+ progress.Exception.InnerException
+ Environment.NewLine
+ "HR-Result" + progress.Exception.HResult);
break;
}
}
private void UpdateProgressBar(long value)
{
Dispatcher.Invoke(() => { this.ProgressBar.Value = value; });
}
答案 0 :(得分:0)
我尽可能多地重新创建了您的项目,并在图片上传时正确更新了进度条。鉴于您的回调在写入控制台时仍然有效,因此您可能只是在UI本身使用ProgressBar
的方式存在问题。
请继续阅读,了解我为使其发挥作用所做的工作。
这适用于Google.Cloud.Storage.V1
(不是Google.Apis.Storage.v1
),但现在执行上传似乎更简单一些。我从Client libraries "Getting Started" instructions开始创建服务帐户和存储桶,然后进行实验以了解如何上传图像。
我遵循的流程:
GOOGLE_APPLICATION_CREDENTIALS
的环境变量中 - 我无法通过提供的说明进行操作。事实证明它不是必需的,因为您可以将JSON文件读入字符串并将其传递给客户端构造函数。ViewModel
来容纳应用程序逻辑。 Google.Cloud.Storage.V1
nuget包,它应该引入所需的所有依赖项。代码。
MainWindow.xaml
<StackPanel>
<Button
Margin="50"
Height="50"
Content="BEGIN UPLOAD"
Click="OnButtonClick" />
<ContentControl
Content="{Binding Path=ProgressBar}" />
</StackPanel>
MainWindow.xaml.cs
public partial class MainWindow
{
readonly ViewModel _viewModel;
public MainWindow()
{
_viewModel = new ViewModel(Dispatcher);
DataContext = _viewModel;
InitializeComponent();
}
void OnButtonClick(object sender, RoutedEventArgs args)
{
_viewModel.UploadAsync().ConfigureAwait(false);
}
}
ViewModel.cs
public class ViewModel
{
readonly Dispatcher _dispatcher;
public ViewModel(Dispatcher dispatcher)
{
_dispatcher = dispatcher;
ProgressBar = new ProgressBar {Height=30};
}
public async Task UploadAsync()
{
// Google Cloud Platform project ID.
const string projectId = "project-id-goes-here";
// The name for the new bucket.
const string bucketName = projectId + "-test-bucket";
// Path to the file to upload
const string filePath = @"C:\path\to\image.jpg";
var newObject = new Google.Apis.Storage.v1.Data.Object
{
Bucket = bucketName,
Name = System.IO.Path.GetFileNameWithoutExtension(filePath),
ContentType = "image/jpeg"
};
// read the JSON credential file saved when you created the service account
var credential = Google.Apis.Auth.OAuth2.GoogleCredential.FromJson(System.IO.File.ReadAllText(
@"c:\path\to\service-account-credentials.json"));
// Instantiates a client.
using (var storageClient = Google.Cloud.Storage.V1.StorageClient.Create(credential))
{
try
{
// Creates the new bucket. Only required the first time.
// You can also create buckets through the GCP cloud console web interface
storageClient.CreateBucket(projectId, bucketName);
System.Windows.MessageBox.Show($"Bucket {bucketName} created.");
// Open the image file filestream
using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open))
{
ProgressBar.Maximum = fileStream.Length;
// set minimum chunksize just to see progress updating
var uploadObjectOptions = new Google.Cloud.Storage.V1.UploadObjectOptions
{
ChunkSize = Google.Cloud.Storage.V1.UploadObjectOptions.MinimumChunkSize
};
// Hook up the progress callback
var progressReporter = new Progress<Google.Apis.Upload.IUploadProgress>(OnUploadProgress);
await storageClient.UploadObjectAsync(
newObject,
fileStream,
uploadObjectOptions,
progress: progressReporter)
.ConfigureAwait(false);
}
}
catch (Google.GoogleApiException e)
when (e.Error.Code == 409)
{
// When creating the bucket - The bucket already exists. That's fine.
System.Windows.MessageBox.Show(e.Error.Message);
}
catch (Exception e)
{
// other exception
System.Windows.MessageBox.Show(e.Message);
}
}
}
// Called when progress updates
void OnUploadProgress(Google.Apis.Upload.IUploadProgress progress)
{
switch (progress.Status)
{
case Google.Apis.Upload.UploadStatus.Starting:
ProgressBar.Minimum = 0;
ProgressBar.Value = 0;
break;
case Google.Apis.Upload.UploadStatus.Completed:
ProgressBar.Value = ProgressBar.Maximum;
System.Windows.MessageBox.Show("Upload completed");
break;
case Google.Apis.Upload.UploadStatus.Uploading:
UpdateProgressBar(progress.BytesSent);
break;
case Google.Apis.Upload.UploadStatus.Failed:
System.Windows.MessageBox.Show("Upload failed"
+ Environment.NewLine
+ progress.Exception);
break;
}
}
void UpdateProgressBar(long value)
{
_dispatcher.Invoke(() => { ProgressBar.Value = value; });
}
// probably better to expose progress value directly and bind to
// a ProgressBar in the XAML
public ProgressBar ProgressBar { get; }
}