Warm tip: This article is reproduced from serverfault.com, please click

c#-在单个请求中向API发送多个文件

(c# - Sending Multiple Files in a single Request to API)

发布于 2020-12-22 14:27:41

我对API相当陌生。我正在编写一个“简单” API,该API将.docx文件转换为.pdf文件,并将pdf返回给客户端进行保存。我的代码适用于单个文件,但我想对API进行编码,以在单个请求中处理多个文件。现在,API没有收到请求。如果需要,我可以提供一个文件的工作代码。

我确定我缺少一些简单的东西。请查看下面的内容,看看是否有人可以做得更好,或者为什么API没有收到POST请求。

客户:

        List<string> documents = new List<string>();

        private async void btnConvert_Click(object sender, EventArgs e)
        {
            using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
            {
                client.BaseAddress = new Uri(BaseApiUrl);
                //client.DefaultRequestHeaders.Add("Accept", "application/json");

                // Add an Accept header for JSON format.    
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);

                foreach (string s in docPaths)
                {
                    byte[] bte;
                    bte = File.ReadAllBytes(docPath);

                    string data = JsonConvert.SerializeObject(Convert.ToBase64String(bte));
                    documents.Add(data);                    
                }

                using (var formData = new MultipartFormDataContent())
                {
                    foreach (string s in documents)
                    {
                        //add content to form data
                        formData.Add(new StringContent(s, Encoding.UTF8, "application/json"));
                    }

                    // List of Http Reponse Messages
                    var conversions = documents.Select(doc => client.PostAsync(BaseApiUrl + ApiUrl, formData)).ToList();

                    //Wait for all the requests to finish
                    await Task.WhenAll(conversions);

                    //Get the responses
                    var responses = conversions.Select
                        (
                            task => task.Result
                        );

                    foreach (var r in responses)
                    {
                        // Extract the message body
                        var s = await r.Content.ReadAsStringAsync();
                        SimpleResponse res = JsonConvert.DeserializeObject<SimpleResponse>(s);

                        if (res.Success)
                        {
                            byte[] pdf = Convert.FromBase64String(res.Result.ToString());

                            // Save the PDF here
                        }
                        else
                        {
                           // Log issue
                        }
                    }
                }
            }

API:这没有收到请求,因此此功能不完整。我需要弄清楚为什么它没有被击中。

        [HttpPost]
        public async Task<List<SimpleResponse>> Post([FromBody]string request)
        {
            var response = new List<SimpleResponse>();
            Converter convert = new Converter();

            var provider = new MultipartMemoryStreamProvider();
            await Request.Content.ReadAsMultipartAsync(provider);
            foreach (var requestContents in provider.Contents)
            {
                try
                {
                    //var result = convert.CovertDocToPDF(requestContents, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);

                    //response.Add(new SimpleResponse() { Result = result, Success = true });
                }
                catch (Exception ex)
                {
                    response.Add(new SimpleResponse() { Success = false, Exception = ex, Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") } });
                }
            }

            return response;
        }

SimpleResponse模型:

    public class SimpleResponse
    {
        public object Result { get; set; }
        public bool Success { get; set; }
        public Exception Exception { get; set; }
        public List<string> Errors { get; set; }
    }

更新

@jdweng提出了建议吗,我在API POST上得到的响应为空

客户:

        public async void btnConvert_Click(object sender, EventArgs e)
        {
            using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
            {
                client.BaseAddress = new Uri(BaseApiUrl);
                client.DefaultRequestHeaders.Add("Accept", "application/json");

                // Add an Accept header for JSON format.    
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//application/json
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);

                List<string> requests = new List<string>();
                byte[] bte;

                // New Code per the suggestion
                foreach (string s in docPaths)
                {
                     bte = File.ReadAllBytes(s);

                    requests.Add(Convert.ToBase64String(bte));
                }
                // End new code

                string data = JsonConvert.SerializeObject(requests);

                request.Content = new StringContent(data, Encoding.UTF8, "application/json");

                HttpResponseMessage response1 = client.PostAsync(BaseApiUrl + ApiUrl, request.Content).Result;
                Task<string> json = response1.Content.ReadAsStringAsync();

                SimpleResponse response = JsonConvert.DeserializeObject<SimpleResponse>(json.Result);
                //result = JsonConvert.DeserializeObject(result).ToString();

                if (response.Success)
                {
                    bte = Convert.FromBase64String(response.Result.ToString());

                    if (File.Exists(tempPdfPath))
                    {
                        File.Delete(tempPdfPath);
                    }
                    System.IO.File.WriteAllBytes(tempPdfPath, bte);
                }
                else
                {

                }
            }
        }

服务器:

        [HttpPost]
        public async Task<List<SimpleResponse>> Post([FromBody]string request)
        {
            // The request in NULL....

            List<SimpleResponse> responses = new List<SimpleResponse>();

            List<string> resp = JsonConvert.DeserializeObject(request) as List<string>;
            try
            {
                Converter convert = new Converter();

                foreach (string s in resp)
                {
                    var result = convert.CovertDocToPDF(request, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);

                    responses.Add(new SimpleResponse()
                    {
                        Result = result,
                        Success = true
                    });
                }

            }
            catch (Exception ex)
            {
                responses.Add(new SimpleResponse()
                {
                    Result = null,
                    Success = true,
                    Exception = ex,
                    Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") }
                });
            }

            return responses;
        }

Questioner
Michael Brown
Viewed
0
Michael Brown 2021-01-06 23:13:32

我终于解决了问题,现在可以成功地将多个.docx文件发送到API并从API取回.pdf文件。现在,我想弄清楚如何在其自己的线程上而不是一起发送每个文件。

客户:

        public async void btnConvert_Click(object sender, EventArgs e)
        {
            using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
            {
                client.BaseAddress = new Uri(BaseApiUrl);
                client.DefaultRequestHeaders.Add("Accept", "application/json");

                // Add an Accept header for JSON format.    
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + ApiUrl);

                List<string> requests = new List<string>();
                byte[] bte;
                foreach (string s in docPaths)
                {
                     bte = File.ReadAllBytes(s);

                    requests.Add(Convert.ToBase64String(bte));
                }

                var data = JsonConvert.SerializeObject(requests);

                request.Content = new StringContent(data, Encoding.UTF8, "application/json");

                HttpResponseMessage response1 = await client.PostAsync(BaseApiUrl + ApiUrl, request.Content);
                Task<string> json = response1.Content.ReadAsStringAsync();

                var response = JsonConvert.DeserializeObject<List<SimpleResponse>>(json.Result);

                foreach (SimpleResponse sr in response)
                {
                    if (sr.Success)
                    {
                        bte = Convert.FromBase64String(sr.Result.ToString());

                        string rs = RandomString(16, true);
                        string pdfFileName = tempPdfPath + rs + ".pdf";
                        
                        if (File.Exists(pdfFileName))
                        {
                            File.Delete(pdfFileName);
                        }
                        System.IO.File.WriteAllBytes(pdfFileName, bte);
                    }
                    else
                    {
                    }
                }
            }
        }

API:

        [HttpPost]
        public async Task<List<SimpleResponse>> Post([FromBody] List<string> request)
        {
            List<SimpleResponse> responses = new List<SimpleResponse>();

            try
            {
                Converter convert = new Converter();

                foreach (string s in request)
                {
                    var result = convert.CovertDocToPDF(s, WebConfigurationManager.AppSettings["tempDocPath"], WebConfigurationManager.AppSettings["tempPdfPath"]);

                    responses.Add(new SimpleResponse()
                    {
                        Result = result,
                        Success = true
                    });
                }
            }
            catch (Exception ex)
            {
                responses.Add(new SimpleResponse()
                {
                    Result = null,
                    Success = true,
                    Exception = ex,
                    Errors = new List<string>() { string.Format("{0}, {1}", ex.Message, ex.InnerException?.Message ?? "") }
                });
            }

            return responses;
        }