POST到外部API后,如何使用Task.Delay调用GET响应?

时间:2019-11-05 15:53:50

标签: c# .net wpf rest httpclient

我正在尝试将外部API的使用与我的C#WPF客户端应用程序集成在一起以执行POST和GET调用。 https://developers.virustotal.com/reference

我有以下代码:

InfoProcessor.xaml.cs

        public static async Task<InfoModel> LoadInfo(string infoVar)
        {
            string apiKey = "xxxxxxxxxxxxx";
            //string resourceKey = "efbb7149e39e70c84fe72c6fe8cef5d379fe37e7238d19a8a4536fb2a3146aed"; 
            string resourceKey = infoVar;
            string url = $"https://www.virustotal.com/vtapi/v2/file/report?apikey={apiKey}&resource={resourceKey}";
            //await Task.Delay(30000);
            using (HttpResponseMessage response = await ApiStartup.ApiClient.GetAsync(url))
            {
                if (response.IsSuccessStatusCode)
                {
                    InfoModel info = await response.Content.ReadAsAsync<InfoModel>();

                    return info;
                }
                else
                {
                    throw new Exception(response.ReasonPhrase);
                }
            }
        }

        public static async Task<InfoModel> PostFileInfo(string filePath)
        {

            string url = "https://www.virustotal.com/vtapi/v2/file/scan";

            ApiStartup.ApiClient.DefaultRequestHeaders.Add("User-Agent", "VT API Service");

            using (var content = new MultipartFormDataContent())
            {
                var path = filePath;

                string assetName = Path.GetFileName(path);

                FileStream fs = File.OpenRead(path);

                var streamContent = new StreamContent(fs);
                streamContent.Headers.Add("Content-Type", "application/octet-stream");
                streamContent.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"" + Path.GetFileName(path) + "\"");
                content.Add(streamContent, "file", Path.GetFileName(path));
                content.Add(CreateApiPart());

                //content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");


                Task<HttpResponseMessage> message = ApiStartup.ApiClient.PostAsync(url, content);

                InfoModel info = await message.Result.Content.ReadAsAsync<InfoModel>();
                return info;

            }



        }

ScanPage.xaml.cs

        string filePath;
        private void browseFileButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Multiselect = false;
            openFileDialog.Filter = "All files (*.*)|*.*";
            openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            if (openFileDialog.ShowDialog() == true)
            {
                filePath = openFileDialog.FileName;
                fileLocation.Text = filePath;
            }
        }

private async void uploadFileButton_Click(object sender, RoutedEventArgs e)
        {
            if (filePath != null)
            {
                //await InfoProcessor.PostFileInfo(filePath, "https://www.virustotal.com/vtapi/v2/url/scan",);

                responseText.Text = "File queued for scanning, please wait a moment...";
                //var resultInfo = await InfoProcessor.PostInfo(filePath);
                var resultInfo = await InfoProcessor.PostFileInfo(filePath);
                await Task.Delay(60000);
                var resultInfo2 = await InfoProcessor.LoadInfo(resultInfo.Resource);
                //await Task.Delay(30000);
                responseText.Text = $"Scan Completed, MD5 checksum of file is {resultInfo2.Sha256} \n {resultInfo2.Positives} out of {resultInfo2.Total} {resultInfo2.Permalink} scan engines has detected to be potentially malicious";
            }
            else
            {
                MessageBox.Show("please upload a file");
            }
        }

选择并上传文件后,将使用PostFileInfo函数上传和扫描文件,然后将响应内容resource id插入到LoadInfo函数中作为参数。

在扫描文件时,应加载的其余响应内容(例如md5 / sha256 / sha1值)将为空,直到扫描完成为止,这意味着我将需要执行在PostFileInfo和LoadInfo函数之间的Task.Delay函数。

但是,即使在函数之间延迟60秒之后,结果也不会出现在responseText.Text中,直到我在一段时间后再次调用它为止。我可以正确实现Task.Delay函数吗?

2 个答案:

答案 0 :(得分:0)

在对上一个问题的评论中,我发布了带有示例代码的存储库链接。 从那里:

https://github.com/Genbox/VirusTotalNet/blob/master/src/VirusTotalNet.Examples/Program.cs

Program.cs似乎正在执行您想做的事情:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading.Tasks;
    using VirusTotalNet.Objects;
    using VirusTotalNet.ResponseCodes;
    using VirusTotalNet.Results;

    namespace VirusTotalNet.Examples
    {
        internal class Program
        {
            private static async Task Main(string[] args)
            {
                VirusTotal virusTotal = new VirusTotal("YOUR API KEY HERE");

                //Use HTTPS instead of HTTP
                virusTotal.UseTLS = true;

                //Create the EICAR test virus. See http://www.eicar.org/86-0-Intended-use.html
                byte[] eicar = Encoding.ASCII.GetBytes(@"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*");

                //Check if the file has been scanned before.
                FileReport fileReport = await virusTotal.GetFileReportAsync(eicar);

                bool hasFileBeenScannedBefore = fileReport.ResponseCode == FileReportResponseCode.Present;

                Console.WriteLine("File has been scanned before: " + (hasFileBeenScannedBefore ? "Yes" : "No"));

                //If the file has been scanned before, the results are embedded inside the report.
                if (hasFileBeenScannedBefore)
                {
                    PrintScan(fileReport);
                }
                else
                {
                    ScanResult fileResult = await virusTotal.ScanFileAsync(eicar, "EICAR.txt");
                    PrintScan(fileResult);
                }

                Console.WriteLine();

                string scanUrl = "http://www.google.com/";

                UrlReport urlReport = await virusTotal.GetUrlReportAsync(scanUrl);

                bool hasUrlBeenScannedBefore = urlReport.ResponseCode == UrlReportResponseCode.Present;
                Console.WriteLine("URL has been scanned before: " + (hasUrlBeenScannedBefore ? "Yes" : "No"));

                //If the url has been scanned before, the results are embedded inside the report.
                if (hasUrlBeenScannedBefore)
                {
                    PrintScan(urlReport);
                }
                else
                {
                    UrlScanResult urlResult = await virusTotal.ScanUrlAsync(scanUrl);
                    PrintScan(urlResult);
                }
            }

            private static void PrintScan(UrlScanResult scanResult)
            {
                Console.WriteLine("Scan ID: " + scanResult.ScanId);
                Console.WriteLine("Message: " + scanResult.VerboseMsg);
                Console.WriteLine();
            }

            private static void PrintScan(ScanResult scanResult)
            {
                Console.WriteLine("Scan ID: " + scanResult.ScanId);
                Console.WriteLine("Message: " + scanResult.VerboseMsg);
                Console.WriteLine();
            }

            private static void PrintScan(FileReport fileReport)
            {
                Console.WriteLine("Scan ID: " + fileReport.ScanId);
                Console.WriteLine("Message: " + fileReport.VerboseMsg);

                if (fileReport.ResponseCode == FileReportResponseCode.Present)
                {
                    foreach (KeyValuePair<string, ScanEngine> scan in fileReport.Scans)
                    {
                        Console.WriteLine("{0,-25} Detected: {1}", scan.Key, scan.Value.Detected);
                    }
                }

                Console.WriteLine();
            }

            private static void PrintScan(UrlReport urlReport)
            {
                Console.WriteLine("Scan ID: " + urlReport.ScanId);
                Console.WriteLine("Message: " + urlReport.VerboseMsg);

                if (urlReport.ResponseCode == UrlReportResponseCode.Present)
                {
                    foreach (KeyValuePair<string, UrlScanEngine> scan in urlReport.Scans)
                    {
                        Console.WriteLine("{0,-25} Detected: {1}", scan.Key, scan.Value.Detected);
                    }
                }

                Console.WriteLine();
            }
        }
    }

答案 1 :(得分:-1)

您是否可以编写一些代码来检查要在其中查找值的字段中是否有值,然后仅在找到该值后才继续,而不是花X秒的延迟?