C# 从blobstorage获取资源文件并添加到azure批处理中的任务

C# 从blobstorage获取资源文件并添加到azure批处理中的任务,c#,asp.net,azure,razor-pages,C#,Asp.net,Azure,Razor Pages,我是Azure和Azure批处理服务的新手。我创建了一个简单的.NET应用程序,它应该在某个输入文件上运行一些代码。这就是我开始创建作业、任务和添加资源文件的方式,然后应用程序包将处理这些文件 一,。创建BlobClient等: // Create the blob client, for use in obtaining references to blob storage containers CloudBlobClient blobClient = Crea

我是Azure和Azure批处理服务的新手。我创建了一个简单的.NET应用程序,它应该在某个输入文件上运行一些代码。这就是我开始创建作业、任务和添加资源文件的方式,然后应用程序包将处理这些文件

一,。创建BlobClient等:

        // Create the blob client, for use in obtaining references to blob storage containers
        CloudBlobClient blobClient = CreateCloudBlobClient(StorageAccountName, StorageAccountKey);

        // Use the blob client to create the input container in Azure Storage 
        const string inputContainerName = "modelinput";

        CloudBlobContainer container = blobClient.GetContainerReference(inputContainerName);

        container.CreateIfNotExistsAsync().Wait();
二,。此处,将上载放置在应用程序目录中的文件,并将其添加到资源文件列表中:

         List<ResourceFile> inputFiles = new List<ResourceFile>();

//upload the file that should be processed and add to resourcefiles
inputFiles.Add(UploadFileToContainer(blobClient, inputContainerName, "myinputfile.xml"))
三,。创建批处理作业和任务

    BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

        using (BatchClient batchClient = BatchClient.Open(cred))
        {

            Console.WriteLine("Creating job [{0}]...", JobId);


                CloudJob job = batchClient.JobOperations.CreateJob();
                job.Id = JobId;
                job.PoolInformation = new PoolInformation { PoolId = PoolId }; 

                job.Commit();

        List<CloudTask> tasks = new List<CloudTask>();

        string taskId = String.Format("Task{0}", 0);
        string inputFilename = inputFiles[0].FilePath;

        //set the commandline 
        string taskCommandLine = String.Format("cmd /c %AZ_BATCH_APP_PACKAGE_DEVBATCHAPP%\\batchapp.exe {0}", inputFilename);

        CloudTask task = new CloudTask(taskId, taskCommandLine)

         //add my resourcefiles to the task
        task.ResourceFiles = new List<ResourceFile> { inputFiles[0] }; 

        task.ApplicationPackageReferences = new List<ApplicationPackageReference>{new ApplicationPackageReference{ApplicationId = "devbatchapp",Version = "0.0.1"}};

        tasks.Add(task);
     }
如果我现在运行任务,一切都会完美运行。但是现在我开发了一个ASP.NET Razor Pages应用程序,用户可以通过它选择并上传文件。因为我现在只能用一个文件流来上传我的文件,所以我不得不改变2。对于类似的内容,主要遵循以下文档:


代码的其余部分基本保持不变。但是现在,当我尝试运行任务时,我得到一个blobdownloadmics错误。在批处理资源管理器中进行分析时,我发现如果手动将资源文件添加到任务中,则资源文件的URL显然是错误的。有人能帮我吗?如何获得正确的资源文件源以将其添加到任务中?

根据我的测试,您可能没有使用正确的权限。有关更多详细信息,请参阅。此外,请确保您的存储帐户已链接到您的批处理帐户

对于容器访问,您必须同时具有读取和列表权限, 而对于blob访问,您只需要读取权限

我的代码如下

string containerSasToken = container.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
    SharedAccessStartTime = DateTime.UtcNow,
    SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddDays(1),
    Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List
});

string containerSasUrl = String.Format("{0}{1}", container.Uri, containerSasToken);
var inputFiles = new List<ResourceFile> { };
var file = ResourceFile.FromStorageContainerUrl(containerSasUrl,"test");
inputFiles.Add(file);
Console.WriteLine(inputFiles.Count);

// Get a Batch client using account creds

BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

using (BatchClient batchClient = BatchClient.Open(cred))
{
    Console.WriteLine("getting pool [{0}]...", PoolId);


    batchClient.PoolOperations.GetPool(PoolId);
    
    // Create a Batch job
    Console.WriteLine("Creating job [{0}]...", JobId);

    try
    {
        CloudJob job = batchClient.JobOperations.CreateJob();
        job.Id = JobId;
        job.PoolInformation = new PoolInformation { PoolId = PoolId };

        job.Commit();
    }
    catch (BatchException be)
    {
        // Accept the specific error code JobExists as that is expected if the job already exists
        if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.JobExists)
        {
            Console.WriteLine("The job {0} already existed when we tried to create it", JobId);
        }
        else
        {
            throw; // Any other exception is unexpected
        }
    }

    // Create a collection to hold the tasks that we'll be adding to the job

    Console.WriteLine("Adding {0} tasks to job [{1}]...", inputFiles.Count, JobId);

    List<CloudTask> tasks = new List<CloudTask>();

    // Create each of the tasks to process one of the input files. 

    for (int i = 0; i < inputFiles.Count; i++)
    {
        string taskId = String.Format("Task{0}", i);
        string inputFilename = inputFiles[i].FilePath;
        string taskCommandLine = String.Format("cmd /c type {0}", inputFilename);

        CloudTask task = new CloudTask(taskId, taskCommandLine);
        task.ResourceFiles = new List<ResourceFile> { inputFiles[i] };
        tasks.Add(task);
    }

    // Add all tasks to the job.
    batchClient.JobOperations.AddTask(JobId, tasks);


    // Monitor task success/failure, specifying a maximum amount of time to wait for the tasks to complete.

    TimeSpan timeout = TimeSpan.FromMinutes(30);
    Console.WriteLine("Monitoring all tasks for 'Completed' state, timeout in {0}...", timeout);

    IEnumerable<CloudTask> addedTasks = batchClient.JobOperations.ListTasks(JobId);

    batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

    Console.WriteLine("All tasks reached state Completed.");

    // Print task output
    Console.WriteLine();
    Console.WriteLine("Printing task output...");
}

请尝试删除这行代码:containerSas=blobstore.Uri.AbsoluteUri+containerSasToken;请尝试转换代码行:containerSas=blobstore.Uri.AbsoluteUri+containerSasToken;字符串containerSasUrl=string.Format{0}{1},container.Uri,containerSasToken;无论如何,我必须重写那段代码,现在它可以工作了…新版本包括Jim版本的containerSas系列-不确定这是否是它现在可以工作的原因以及与原始版本的区别。谢谢你的回答,权限和链接的存储帐户都已就位……我最终重写了整个代码。现在它的结构有点不同,它突然工作了,不知道为什么。@Hatzegopteryx权限SharedAccessBlobPermissions.List允许您访问容器。我想如果您没有权限,当您运行ResourceFile.FromStorageContainerUrlContainerAs,myinput时,您将无法访问容器然后获取blob。@Hatzegopteryx如果我的答案对您有帮助,您可以将其作为答案接受单击答案旁边的复选标记,将其从灰色变为填充。。这可能对其他社区成员有益。谢谢。但是我担心你的回答并没有真正解决我的问题,尽管我不确定最终是什么解决了这个问题。我给了你一票,但因为我的声誉太低,所以看不见。。。
string containerSasToken = container.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
    SharedAccessStartTime = DateTime.UtcNow,
    SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddDays(1),
    Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List
});

string containerSasUrl = String.Format("{0}{1}", container.Uri, containerSasToken);
var inputFiles = new List<ResourceFile> { };
var file = ResourceFile.FromStorageContainerUrl(containerSasUrl,"test");
inputFiles.Add(file);
Console.WriteLine(inputFiles.Count);

// Get a Batch client using account creds

BatchSharedKeyCredentials cred = new BatchSharedKeyCredentials(BatchAccountUrl, BatchAccountName, BatchAccountKey);

using (BatchClient batchClient = BatchClient.Open(cred))
{
    Console.WriteLine("getting pool [{0}]...", PoolId);


    batchClient.PoolOperations.GetPool(PoolId);
    
    // Create a Batch job
    Console.WriteLine("Creating job [{0}]...", JobId);

    try
    {
        CloudJob job = batchClient.JobOperations.CreateJob();
        job.Id = JobId;
        job.PoolInformation = new PoolInformation { PoolId = PoolId };

        job.Commit();
    }
    catch (BatchException be)
    {
        // Accept the specific error code JobExists as that is expected if the job already exists
        if (be.RequestInformation?.BatchError?.Code == BatchErrorCodeStrings.JobExists)
        {
            Console.WriteLine("The job {0} already existed when we tried to create it", JobId);
        }
        else
        {
            throw; // Any other exception is unexpected
        }
    }

    // Create a collection to hold the tasks that we'll be adding to the job

    Console.WriteLine("Adding {0} tasks to job [{1}]...", inputFiles.Count, JobId);

    List<CloudTask> tasks = new List<CloudTask>();

    // Create each of the tasks to process one of the input files. 

    for (int i = 0; i < inputFiles.Count; i++)
    {
        string taskId = String.Format("Task{0}", i);
        string inputFilename = inputFiles[i].FilePath;
        string taskCommandLine = String.Format("cmd /c type {0}", inputFilename);

        CloudTask task = new CloudTask(taskId, taskCommandLine);
        task.ResourceFiles = new List<ResourceFile> { inputFiles[i] };
        tasks.Add(task);
    }

    // Add all tasks to the job.
    batchClient.JobOperations.AddTask(JobId, tasks);


    // Monitor task success/failure, specifying a maximum amount of time to wait for the tasks to complete.

    TimeSpan timeout = TimeSpan.FromMinutes(30);
    Console.WriteLine("Monitoring all tasks for 'Completed' state, timeout in {0}...", timeout);

    IEnumerable<CloudTask> addedTasks = batchClient.JobOperations.ListTasks(JobId);

    batchClient.Utilities.CreateTaskStateMonitor().WaitAll(addedTasks, TaskState.Completed, timeout);

    Console.WriteLine("All tasks reached state Completed.");

    // Print task output
    Console.WriteLine();
    Console.WriteLine("Printing task output...");
}