【问题标题】:How to upload a file to azure Blob storage through IOT hub from a Xamarin PCL project如何通过 IOT 集线器从 Xamarin PCL 项目将文件上传到 azure Blob 存储
【发布时间】:2018-02-15 00:37:38
【问题描述】:

所以我需要将此 json 文件从我的 IotHub 上传到我的 AzureBlob 存储。 到目前为止,我有一个存储帐户和一个链接到我的 IoT 中心的容器。 我有一个链接到 3 个平台项目(Android、iOS 和 UWP)的 PCL 项目。 在我的 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);
}

但我没有在 IntelliSense 上获得方法“UploadToBlobAsync”。

我正在使用 VS2017。

已添加 NuGet 包:Microsoft.Azure.Devices.Client.PCL

我的 IOTHubHelper 类引用了 Microsoft.Azure.Devices.Client;

【问题讨论】:

    标签: c# azure xamarin file-upload azure-iot-hub


    【解决方案1】:

    已添加 NuGet 包:Microsoft.Azure.Devices.Client.PCL

    但我没有在 IntelliSense 上获得方法“UploadToBlobAsync”。

    作为Microsoft.Azure.Devices.Client的源代码Azure/azure-iot-sdk-csharpDeviceClient.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 Standard 库并使用 Microsoft.Azure.Devices.Client 将文件上传到 Azure Blob 存储。此外,您可以关注tutorial,了解使用 .NET Standard 构建 Xamarin.Forms 应用程序。

    【讨论】:

      【解决方案2】:

      方法 Microsoft.Azure.Devices.Client.DeviceClient.UploadToBlobAsync 基本上是通过 Azure IoT 中心对 Blob 上传会话的 REST API 调用进行封装。本次会议的顺序分为 3 个步骤,例如: 第 1 步。从 Azure IoT 中心获取上传信息参考(开放会话) 第 2 步。根据收到的参考信息上传 blob 第 3 步。关闭发布上传过程结果的会话。

      以下代码 sn -p 显示了在 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,所以下面的代码sn-p展示了它的实现:

          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 中的重试机制。

      【讨论】:

        猜你喜欢
        • 2022-01-12
        • 1970-01-01
        • 2022-01-12
        • 2019-08-13
        • 1970-01-01
        • 2021-03-07
        • 2017-01-24
        • 2017-08-19
        相关资源
        最近更新 更多