所以我需要从IotHub上传这个json文件到我的AzureBlob存储。 到目前为止,我有一个存储帐户和一个链接到我的IoT HUb的容器。 我有一个PCL项目,链接到3个平台项目(Android,iOS和UWP)。 在我的PCL项目中,我有一个deviceClient,否则会发送遥测数据。
我尝试使用https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-csharp-csharp-file-upload
中的这段代码private static async void SendToBlobAsync()
{
string fileName = "data.json";
Console.WriteLine("Uploading file: {0}", fileName);
var watch = System.Diagnostics.Stopwatch.StartNew();
using (var sourceData = new FileStream(@"image.jpg", FileMode.Open))
{
await deviceClient.UploadToBlobAsync(fileName, sourceData);
}
watch.Stop();
Console.WriteLine("Time to upload file: {0}ms\n",batch.ElapsedMilliseconds);
}
但我没有得到方法" UploadToBlobAsync"关于智能感知。
我正在使用VS2017。
添加了NuGet包:Microsoft.Azure.Devices.Client.PCL
我的IOTHubHelper类引用了Microsoft.Azure.Devices.Client;
答案 0 :(得分:0)
添加了NuGet包:Microsoft.Azure.Devices.Client.PCL
但我没有在IntelliSense上获得“UploadToBlobAsync”方法。
Microsoft.Azure.Devices.Client
关于Azure/azure-iot-sdk-csharp的srouce代码DeviceClient.cs定义如下:
#if !PCL
/// <summary>
/// Uploads a stream to a block blob in a storage account associated with the IoTHub for that device.
/// If the blob already exists, it will be overwritten.
/// </summary>
/// <param name="blobName"></param>
/// <param name="source"></param>
/// <returns>AsncTask</returns>
public Task UploadToBlobAsync(String blobName, System.IO.Stream source)
{
if (String.IsNullOrEmpty(blobName))
{
throw Fx.Exception.ArgumentNull("blobName");
}
if (source == null)
{
throw Fx.Exception.ArgumentNull("source");
}
if (blobName.Length > 1024)
{
throw Fx.Exception.Argument("blobName", "Length cannot exceed 1024 characters");
}
if (blobName.Split('/').Count() > 254)
{
throw Fx.Exception.Argument("blobName", "Path segment count cannot exceed 254");
}
HttpTransportHandler httpTransport = null;
#if !WINDOWS_UWP
//We need to add the certificate to the fileUpload httpTransport if DeviceAuthenticationWithX509Certificate
if (this.Certificate != null)
{
Http1TransportSettings transportSettings = new Http1TransportSettings();
transportSettings.ClientCertificate = this.Certificate;
httpTransport = new HttpTransportHandler(null, iotHubConnectionString, transportSettings);
}
else
{
httpTransport = new HttpTransportHandler(iotHubConnectionString);
}
#else
httpTransport = new HttpTransportHandler(iotHubConnectionString);
#endif
return httpTransport.UploadToBlobAsync(blobName, source);
}
#endif
注意: PCL库不支持UploadToBlobAsync
功能。我假设您可以将PCL迁移到.NET标准库,并使用Microsoft.Azure.Devices.Client将文件上载到Azure Blob存储。此外,您可以按照tutorial关于使用.NET Standard构建Xamarin.Forms应用程序。
答案 1 :(得分:0)
方法 Microsoft.Azure.Devices.Client.DeviceClient.UploadToBlobAsync 基本上是围绕通过Azure IoT Hub进行blob上载会话的REST API调用的包装器。此会话的顺序分为3个步骤,例如: 第1步。从Azure IoT Hub获取上载信息参考(打开会话) 第2步。根据收到的参考信息上传blob 第3步。关闭发布上传过程结果的会话。
以下代码段显示了在PCL项目中实现的上述步骤的示例:
private async Task UploadToBlobAsync(string blobName, Stream source, string iothubnamespace, string deviceId, string deviceKey)
{
using(HttpClient client = new HttpClient())
{
// create authorization header
string deviceSasToken = GetSASToken($"{iothubnamespace}.azure-devices.net/devices/{deviceId}", deviceKey, null, 1);
client.DefaultRequestHeaders.Add("Authorization", deviceSasToken);
// step 1. get the upload info
var payload = JsonConvert.SerializeObject(new { blobName = blobName });
var response = await client.PostAsync($"https://{iothubnamespace}.azure-devices.net/devices/{deviceId}/files?api-version=2016-11-14", new StringContent(payload, Encoding.UTF8, "application/json"));
var infoType = new { correlationId = "", hostName = "", containerName = "", blobName = "", sasToken = "" };
var uploadInfo = JsonConvert.DeserializeAnonymousType(await response.Content.ReadAsStringAsync(), infoType);
// step 2. upload blob
var uploadUri = $"https://{uploadInfo.hostName}/{uploadInfo.containerName}/{uploadInfo.blobName}{uploadInfo.sasToken}";
client.DefaultRequestHeaders.Add("x-ms-blob-type", "blockblob");
client.DefaultRequestHeaders.Remove("Authorization");
response = await client.PutAsync(uploadUri, new StreamContent(source));
// step 3. send completed
bool isUploaded = response.StatusCode == System.Net.HttpStatusCode.Created;
client.DefaultRequestHeaders.Add("Authorization", deviceSasToken);
payload = JsonConvert.SerializeObject(new { correlationId = uploadInfo.correlationId, statusCode = isUploaded ? 0 : -1, statusDescription = response.ReasonPhrase, isSuccess = isUploaded });
response = await client.PostAsync($"https://{iothubnamespace}.azure-devices.net/devices/{deviceId}/files/notifications?api-version=2016-11-14", new StringContent(payload, Encoding.UTF8, "application/json"));
}
}
对于授权标头我们需要一个sasToken,因此以下代码片段显示了它的实现:
private string GetSASToken(string resourceUri, string key, string keyName = null, uint hours = 24)
{
var expiry = Convert.ToString((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds + 3600 * hours);
string stringToSign = System.Net.WebUtility.UrlEncode(resourceUri) + "\n" + expiry;
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = keyName == null ?
String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}", System.Net.WebUtility.UrlEncode(resourceUri), System.Net.WebUtility.UrlEncode(signature), expiry) :
String.Format(CultureInfo.InvariantCulture, "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}", System.Net.WebUtility.UrlEncode(resourceUri), System.Net.WebUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
请注意,上述实现并未处理步骤2中的重试机制。