C#-如何使用HttpClient对象从JSON API中提取CSV文件?

问题描述

我的公司使用C#.net应用程序以编程方式从供应商网站上以CSV文件的形式检索数据。但是,供应商最近将其API更改为JSON API。我是一个新手程序员,对JSON API的调用没有任何经验。当供应商注册我的新API用户ID时,他们提供了如何使用 curl 下载必要的csv数据文件的示例。这是示例:

echo 'Going to log in to sso'
data=$(curl -c cookies.txt -X POST https://sso.theice.com/api/authenticateTfa -H "Content-Type: application/json" \
--data '{"userId":"yourApiUserId","password":"yourpassword","appKey":"yourAppKey"}')

echo 'Going to download icecleared_oil_2020_06_26.dat file from Settlement_Reports_CSV/Oil'
curl -b cookies.txt -O ' https://downloads2.theice.com/Settlement_Reports_CSV/Oil/icecleared_oil_2020_06_26.dat

由于我没有Curl的经验,因此我使用https://curl.olsh.me/将上面的示例转换为C#。这样做会生成以下代码

//Authenticate userId (and get cookie?)
using (var httpClient = new HttpClient())
{
    using (var request = new HttpRequestMessage(new HttpMethod("POST"),"https://sso.theice.com/api/authenticateTfa"))
    {
        request.Content = new StringContent("{\"userId\":\"yourApiUserId\",\"password\":\"yourpassword\",\"appKey\":\"yourAppKey\"}");
        request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); 

        var response = await httpClient.SendAsync(request);
    }
}

//Using authentication cookie,from prevIoUs code block,retrieve dat file
var handler = new httpclienthandler();
handler.UseCookies = false;

using (var httpClient = new HttpClient(handler))
{
    using (var request = new HttpRequestMessage(new HttpMethod("GET"),"https://downloads2.theice.com/Settlement_Reports_CSV/Oil/icecleared_oil_2020_06_26.dat"))
    {
        request.Headers.TryAddWithoutValidation("Cookie","cookies.txt");

        var response = await httpClient.SendAsync(request);
    }
}

我将此代码集成到我的项目中,并能够获取它来验证我的userID(POST请求),但是我一生都无法弄清楚如何从第二个代码块(GET请求)中检索DAT文件)。我观察到,无论我是否成功登录POST请求,GET请求的响应都是相同的。此时,我假设GET请求没有从POST请求中获取验证cookie,但是即使这样,我也不知道如何从GET请求中的响应对象中提取文件。>

有人可以建议我需要做什么吗?下面是已集成到我的项目中的代码

public async Task DownloadAsync(List<string> iceReportFileNamesFullUrl)
{
    await AuthenticateUserCredentialsOnICE();
    await RetrieveIceRportFiles(iceReportFileNamesFullUrl);

}

private async Task AuthenticateUserCredentialsOnICE()
{
    using (HttpClient httpClient = new HttpClient())
    {
        using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("POST"),"https://sso.theice.com/api/authenticateTfa"))
        {               
            request.Content = new StringContent("{\"userId\":\"xxxxxxxxx\",\"password\":\"xxxxxxxxxx\",\"appKey\":\"xxxxxxxxxxx\"}");
            request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

            HttpResponseMessage response = await httpClient.SendAsync(request);
            var value = response.Content.ReadAsstringAsync();
        }
    }
}
private static async Task RetrieveIceRportFiles(List<string> iceReportFileNamesFullUrl)
{
    foreach (string iceReportUrl in iceReportFileNamesFullUrl)
    {
        httpclienthandler handler = new httpclienthandler();
        handler.UseCookies = false;

        using (HttpClient httpClient = new HttpClient(handler))
        {
            using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("GET"),iceReportUrl))
            {
                request.Headers.TryAddWithoutValidation("Cookie","cookies.txt");

                HttpResponseMessage response = await httpClient.SendAsync(request);
                var value = response.Content.ReadAsstringAsync();

            }
        }
    }
}

-更新:2020年8月25日-

谢谢大家的评论。您清楚地表明,我没有从POST请求中捕获Cookie。经过一些研究(thisthisthis),我更新了代码,以便现在可以成功下载CSV / DAT文件。我已经发布了下面的内容,尽管它仍然需要错误处理,登录失败的检查等。我也肯定会有关键的反馈。

这里是:

private CookieContainer authenticationCookieContainer;
//main method for downloading file
public async Task DownloadAsync(string iceReportDownloadUrl)
{
    await AuthenticateUserCredentialsOnIceAsync();
    await SendDownloadReportRequestAsync(iceReportDownloadUrl);
}

通过JSON API对凭据进行身份验证,并将身份验证cookie存储在authenticationCookieContainter中

private async Task AuthenticateUserCredentialsOnIceAsync()
{
    //This will contain the ICE authentication cookies
    //if the login is successful
    authenticationCookieContainer = new CookieContainer();

    //Create and assign handler for proxy config and cookie storage
    using (httpclienthandler handler = new httpclienthandler() { CookieContainer = authenticationCookieContainer })
    {
        using (HttpClient httpClient = new HttpClient(handler))
        {
            using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("POST"),"https://sso.theice.com/api/authenticateTfa"))
            {
                request.Content = new StringContent("{\"userId\":\"xxxxxxxxxxx\",\"password\":\"xxxxxxxxxxxxxx\",\"appKey\":\"xxxxxxxxxxxxx\"}");
                request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
                HttpResponseMessage response = await httpClient.SendAsync(request);
            }
        }
    }
}

如果登录成功,则authenticationCookieContainer将包含 登录cookie,并允许您在指定的位置请求数据 网址

private async Task SendDownloadReportRequestAsync(string iceReportDownloadUrl)
{
    if (authenticationCookieContainer != null)
    {
        //Create and assign handler for proxy config and cookie storage
        using (httpclienthandler handler = new httpclienthandler() { CookieContainer = authenticationCookieContainer })
        {
            //Set to true to use the cookies obtained during authentication call
            handler.UseCookies = true;

            using (HttpClient httpClient = new HttpClient(handler))
            {
                Uri iceReportUri = new Uri(iceReportDownloadUrl);
                //Request the ICE data file using the url passed through
                using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("GET"),iceReportUri.AbsoluteUri))
                {
                    HttpResponseMessage response = await httpClient.SendAsync(request);
                    using (Stream responseStream = await response.Content.ReadAsstreamAsync())
                    {
                        //Write the extracted file to the file path
                        byte[] content = StreamToByteArray(responseStream);
                        File.WriteallBytes(@"C:\Users\my.name\Desktop\" + iceReportUri.Segments.Last(),content);
                    }
                }
            }
        } 
    }
}
private static byte[] StreamToByteArray(Stream stream)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        stream.copyTo(memoryStream);
        return memoryStream.ToArray();
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)