我正在尝试从azure blob存储中下载exe文件,并使用除臭容器应用程序将其存储在主机系统上。我是通过在VS2017中创建.netcore项目来编写代码的。这就是我的program.cs的样子:
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Client.Transport.Mqtt;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using System.Reflection;
namespace DocumentFromBlob
{
class Program
{
static void Main(string[] args)
{
// The Edge runtime gives us the connection string we need -- it is injected as an environment variable
// string connectionString = Environment.GetEnvironmentVariable("EdgeHubConnectionString");
string connectionString = "namehost";
// Cert verification is not yet fully functional when using Windows OS for the container
bool bypassCertVerification = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
// if (!bypassCertVerification) InstallCert();
Init(connectionString, bypassCertVerification).Wait();
// Wait until the app unloads or is cancelled
var cts = new CancellationTokenSource();
AssemblyLoadContext.Default.Unloading += (ctx) => cts.Cancel();
Console.CancelKeyPress += (sender, cpe) => cts.Cancel();
WhenCancelled(cts.Token).Wait();
}
/// <summary>
/// Handles cleanup operations when app is cancelled or unloads
/// </summary>
public static Task WhenCancelled(CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).SetResult(true), tcs);
return tcs.Task;
}
/// <summary>
/// Add certificate in local cert store for use by client for secure connection to IoT Edge runtime
/// </summary>
static void InstallCert()
{
string certPath = Environment.GetEnvironmentVariable("EdgeModuleCACertificateFile");
if (string.IsNullOrWhiteSpace(certPath))
{
// We cannot proceed further without a proper cert file
Console.WriteLine($"Missing path to certificate collection file: {certPath}");
throw new InvalidOperationException("Missing path to certificate file.");
}
else if (!File.Exists(certPath))
{
// We cannot proceed further without a proper cert file
Console.WriteLine($"Missing path to certificate collection file: {certPath}");
throw new InvalidOperationException("Missing certificate file.");
}
X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(new X509Certificate2(X509Certificate2.CreateFromCertFile(certPath)));
Console.WriteLine("Added Cert: " + certPath);
store.Close();
}
/// <summary>
/// Initializes the DeviceClient and sets up the callback to receive
/// messages containing temperature information
/// </summary>
static async Task Init(string connectionString, bool bypassCertVerification = false)
{
Console.WriteLine("Connection String {0}", connectionString);
MqttTransportSettings mqttSetting = new MqttTransportSettings(TransportType.Mqtt_Tcp_Only);
// During dev you might want to bypass the cert verification. It is highly recommended to verify certs systematically in production
if (bypassCertVerification)
{
mqttSetting.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
}
ITransportSettings[] settings = { mqttSetting };
// Open a connection to the Edge runtime
DeviceClient ioTHubModuleClient = DeviceClient.CreateFromConnectionString(connectionString, settings);
await ioTHubModuleClient.OpenAsync();
Console.WriteLine("IoT Hub module client initialized.");
// Register callback to be called when a message is received by the module
// await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", PipeMessage, ioTHubModuleClient);
// Attach callback for Twin desired properties updates
// await ioTHubModuleClient.SetDesiredPropertyUpdateCallbackAsync(onDesiredPropertiesUpdate, null);
// Register callback to be called when a message is received by the module
// await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", FilterMessages, ioTHubModuleClient);
DownloadFile();
}
public static async void DownloadFile()
{
string filename = "RDM_WorkFlow.pdf";
string destinationFile = @"D:\Test";
byte[] data = await DownloadFileFromBlob(filename);
WriteFile(filename, data, destinationFile);
}
public static async Task<byte[]> DownloadFileFromBlob(string FileName)
{
CloudBlobContainer container = BlobUtilities.GetBlobClient.GetContainerReference("documents");
// Get reference to blob (binary content)
CloudBlockBlob blockBlob = container.GetBlockBlobReference(FileName);
try
{
//await blockBlob.DownloadToFileAsync(@"D:\Test", FileMode.Create);
using (MemoryStream ms = new MemoryStream())
{
await blockBlob.DownloadToStreamAsync(ms);
return ms.ToArray();
}
}
catch (Exception ex)
{
byte[] bt = null;
return bt;
}
}
public static void WriteFile(string fileName, byte[] bytes, string path)
{
// string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
try
{
var fullpath = Path.Combine(@"C:\Test", fileName);
if (File.Exists(fullpath))
{
File.Delete(fullpath);
}
//// Create the file.
using (FileStream fs = File.Create(fullpath))
{
}
MemoryStream ms = new MemoryStream(bytes);
//write to file
FileStream file = new FileStream(fullpath, FileMode.Create, FileAccess.Write);
ms.WriteTo(file);
file.Close();
ms.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
}
internal class BlobUtilities
{
public static CloudBlobClient GetBlobClient
{
get
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("XYZ;"
+ "AccountKey=+abc=");
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
return blobClient;
}
}
}
}
我在WriteFile函数中遇到异常。我修改了docker-compose.yml文件来共享主机文件系统,它是C:/ Test中的目录。
version: '3'
services:
documentfromblob:
image: documentfromblob
build:
context: .
dockerfile: DocumentFromBlob/Dockerfile
volumes:
- /C/Test
它应该将文件从我的blob复制到C:/ Test目录,但它会抛出异常。我可以使用docker run命令来完成它,但我希望这个容器直接与主机共享文件系统并将文件复制到主机系统。我想应该通过修改.yml文件来完成。我错过了什么吗?