ilovecomputer66 发表于 2023-1-18 09:53

C#内置HttpClient发Multipart请求上传时以及等待服务器处理完上传的下载中,进度怎知?

本帖最后由 ilovecomputer66 于 2023-1-20 18:47 编辑

是这样的,调用第三方平台的API,上传一个本地图片(会很大,几十MB,然后他们服务器处理后,返回下载处理后的图片)

想知道上传的进度(即已经上传多少MB),服务器处理完后,response返回处理后的文件时,也要知道下载进度



看网上有些例子,是还需要再添加包Microsoft.AspNet.WebApi.Client       ,比如:https://blog.csdn.net/adai3846250/article/details/117159419


但我按它这个做,直接程序无法运行,会卡死,但不报错,不知道什么原因(下面button2的点击事件),如果不用文中说的ProgressMessageHandler,不监控进度,即button1我原来写的点击事件,就没问题
(我即便把ProgressMessageHandler_HttpSendProgress 2个函数,里面清空掉),还是会让整个程序卡死,不知道为什么

public partial class Form1 : Form
    {
      public Form1()
      {
            InitializeComponent();
      }

      public void SafeInvoke(Action action)
      {
            if (this.IsDisposed == false && this.Created == true)
            {
                this.Invoke(action);
            }
      }

      private void button1_Click(object sender, EventArgs e)
      {
            HttpClientHandler handler = new HttpClientHandler();
            handler.AllowAutoRedirect = true;
            handler.CheckCertificateRevocationList = false;
            handler.UseCookies = false;

            HttpClient httpClient = new HttpClient(handler);
            httpClient.Timeout = TimeSpan.FromMilliseconds(50000);

            MultipartFormDataContent formData = new MultipartFormDataContent();
            formData.Headers.Add("X-Api-Key", "hdNWthxGKPjxYMxwY1riGvBN"); // hdNWthxGKPjxYMxwY1riGvBN
            formData.Add(new ByteArrayContent(File.ReadAllBytes(@"C:\Users\zhang\Desktop\input2.jpg")), "image_file", "input1.jpg");
            formData.Add(new StringContent("auto"), "size");
            var response = httpClient.PostAsync("https://api.remove.bg/v1.0/removebg", formData).Result;

            if (response.IsSuccessStatusCode)
            {
                FileStream fileStream = new FileStream(@"C:\Users\zhang\Desktop\temp3.jpg", FileMode.Create, FileAccess.Write, FileShare.None);
                response.Content.CopyToAsync(fileStream).ContinueWith((copyTask) => { fileStream.Close(); });
                MessageBox.Show("ok");
            }
            else
            {
                MessageBox.Show("Error: " + response.Content.ReadAsStringAsync().Result);
            }
      }

      private void button2_Click(object sender, EventArgs e)
      {
            HttpClientHandler handler = new HttpClientHandler();
            handler.AllowAutoRedirect = true;
            handler.CheckCertificateRevocationList = false;
            handler.UseCookies = false;

            ProgressMessageHandler progressMessageHandler = new ProgressMessageHandler(handler);
            progressMessageHandler.HttpSendProgress += ProgressMessageHandler_HttpSendProgress;
            progressMessageHandler.HttpReceiveProgress += ProgressMessageHandler_HttpReceiveProgress;

            HttpClient httpClient = new HttpClient(progressMessageHandler);
            httpClient.Timeout = TimeSpan.FromMilliseconds(50000);

            MultipartFormDataContent formData = new MultipartFormDataContent();
            formData.Headers.Add("X-Api-Key", "hdNWthxGKPjxYMxwY1riGvBN"); // hdNWthxGKPjxYMxwY1riGvBN
            formData.Add(new ByteArrayContent(File.ReadAllBytes(@"C:\Users\zhang\Desktop\input3.jpg")), "image_file", "input1.jpg");
            formData.Add(new StringContent("auto"), "size");
            var response = httpClient.PostAsync("https://api.remove.bg/v1.0/removebg", formData).Result;

            if (response.IsSuccessStatusCode)
            {
                FileStream fileStream = new FileStream(@"C:\Users\zhang\Desktop\temp3.jpg", FileMode.Create, FileAccess.Write, FileShare.None);
                response.Content.CopyToAsync(fileStream).ContinueWith((copyTask) => { fileStream.Close(); });
                MessageBox.Show("ok");
            }
            else
            {
                MessageBox.Show("Error: " + response.Content.ReadAsStringAsync().Result);
            }
      }

      private void ProgressMessageHandler_HttpSendProgress(object sender, HttpProgressEventArgs e)
      {
            this.SafeInvoke(() =>
            {
                LblUpload.Text = e.ProgressPercentage + "%";
                this.Refresh();
            });
      }

      private void ProgressMessageHandler_HttpReceiveProgress(object sender, HttpProgressEventArgs e)
      {
            this.SafeInvoke(() =>
            {
                LblDownload.Text = e.ProgressPercentage + "%";
                this.Refresh();
            });
      }
    }

ie81com 发表于 2023-1-18 11:34

var response = httpClient.PostAsync("https://api.remove.bg/v1.0/removebg", formData).Result;

你这把异步转成同步了,换异步试试

ilovecomputer66 发表于 2023-1-18 11:39

ie81com 发表于 2023-1-18 11:34
var response = httpClient.PostAsync("https://api.remove.bg/v1.0/removebg", formData).Result;

你这 ...

我知道,但我说的卡死是程序彻底完蛋,永远执行不下去。目前试的图不大,应该几秒就完。但button2写法永远卡死,button1就瞬间完成

ilovecomputer66 发表于 2023-1-18 11:46

ie81com 发表于 2023-1-18 11:34
var response = httpClient.PostAsync("https://api.remove.bg/v1.0/removebg", formData).Result;

你这 ...

也可能是我理解不对,兄弟按你想的,改一下我代码,我看下你具体想表达什么意思么

ie81com 发表于 2023-1-18 12:12

ilovecomputer66 发表于 2023-1-18 11:46
也可能是我理解不对,兄弟按你想的,改一下我代码,我看下你具体想表达什么意思么

以下代码测试通过

using System.Net.Http.Handlers;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
      public Form1()
      {
            InitializeComponent();
      }

      public void SafeInvoke(Action action)
      {
            if (this.IsDisposed == false && this.Created == true)
            {
                this.Invoke(action);
            }
      }

      private void button1_Click(object sender, EventArgs e)
      {
            HttpClientHandler handler = new HttpClientHandler();
            handler.AllowAutoRedirect = true;
            handler.CheckCertificateRevocationList = false;
            handler.UseCookies = false;

            HttpClient httpClient = new HttpClient(handler);
            httpClient.Timeout = TimeSpan.FromMilliseconds(50000);

            MultipartFormDataContent formData = new MultipartFormDataContent();
            formData.Headers.Add("X-Api-Key", "hdNWthxGKPjxYMxwY1riGvBN"); // hdNWthxGKPjxYMxwY1riGvBN
            formData.Add(new ByteArrayContent(File.ReadAllBytes(@"d:\test.jpg")), "image_file", "test.jpg");
            formData.Add(new StringContent("auto"), "size");
            var response = httpClient.PostAsync("https://api.remove.bg/v1.0/removebg", formData).Result;

            if (response.IsSuccessStatusCode)
            {
                FileStream fileStream = new FileStream(@"d:\test.png", FileMode.Create, FileAccess.Write, FileShare.None);
                response.Content.CopyToAsync(fileStream).ContinueWith((copyTask) => { fileStream.Close(); });
                MessageBox.Show("ok");
            }
            else
            {
                MessageBox.Show("Error: " + response.Content.ReadAsStringAsync().Result);
            }
      }

      private async void button2_Click(object sender, EventArgs e)
      {
            HttpClientHandler handler = new HttpClientHandler();
            handler.AllowAutoRedirect = true;
            handler.CheckCertificateRevocationList = false;
            handler.UseCookies = false;

            ProgressMessageHandler progressMessageHandler = new ProgressMessageHandler(handler);
            progressMessageHandler.HttpSendProgress += ProgressMessageHandler_HttpSendProgress;
            progressMessageHandler.HttpReceiveProgress += ProgressMessageHandler_HttpReceiveProgress;

            HttpClient httpClient = new HttpClient(progressMessageHandler);
            httpClient.Timeout = TimeSpan.FromMilliseconds(50000);

            MultipartFormDataContent formData = new MultipartFormDataContent();
            formData.Headers.Add("X-Api-Key", "hdNWthxGKPjxYMxwY1riGvBN"); // hdNWthxGKPjxYMxwY1riGvBN
            formData.Add(new ByteArrayContent(File.ReadAllBytes(@"d:\test.jpg")), "image_file", "test.jpg");
            formData.Add(new StringContent("auto"), "size");
            var response = await httpClient.PostAsync("https://api.remove.bg/v1.0/removebg", formData);

            if (response.IsSuccessStatusCode)
            {
                FileStream fileStream = new FileStream(@"d:\test.png", FileMode.Create, FileAccess.Write, FileShare.None);
                await response.Content.CopyToAsync(fileStream).ContinueWith((copyTask) => { fileStream.Close(); });
                MessageBox.Show("ok");
            }
            else
            {
                MessageBox.Show("Error: " + response.Content.ReadAsStringAsync().Result);
            }
      }


      private void ProgressMessageHandler_HttpSendProgress(object? sender, HttpProgressEventArgs e)
      {
            this.SafeInvoke(() =>
            {
                LblUpload.Text = e.ProgressPercentage + "%";
                this.Refresh();
            });
      }

      private void ProgressMessageHandler_HttpReceiveProgress(object? sender, HttpProgressEventArgs e)
      {
            this.SafeInvoke(() =>
            {
                LblDownload.Text = e.ProgressPercentage + "%";
                this.Refresh();
            });
      }

    }
}

ilovecomputer66 发表于 2023-1-18 15:18

ie81com 发表于 2023-1-18 12:12
以下代码测试通过

using System.Net.Http.Handlers;

非常感谢。但是,发现上传进度不太对
把回调函数改为打印,结果如下


上传:0%
上传:0%
上传:99%
上传:99%
上传:99%
上传:100%


这是什么原因,按理说上传10MB的,不应该这样。

而下载的处理后的图片更小。却能清晰体现进度
下载:1%
下载:5%
下载:6%
下载:7%
下载:8%
下载:9%
下载:9%
下载:11%
下载:12%
下载:12%
下载:13%
下载:14%
下载:15%
下载:16%
下载:17%
下载:18%
下载:19%
下载:21%
下载:21%
下载:22%
下载:23%
下载:24%
下载:25%
下载:26%
下载:27%
下载:28%
下载:29%
下载:30%
下载:31%
下载:32%
下载:33%
下载:34%
下载:35%
下载:36%
下载:37%
下载:38%
下载:39%
下载:39%
下载:40%
下载:41%
下载:42%
下载:42%
下载:42%
下载:43%
下载:44%
下载:45%
下载:46%
下载:47%
下载:48%
下载:49%
下载:50%
下载:51%
下载:52%
下载:53%
下载:53%
下载:54%
下载:55%
下载:56%
下载:57%
下载:58%
下载:59%
下载:60%
下载:61%
下载:62%
下载:63%
下载:64%
下载:64%
下载:64%
下载:65%
下载:66%
下载:67%
下载:68%
下载:69%
下载:70%
下载:71%
下载:72%
下载:73%
下载:74%
下载:74%
下载:75%
下载:76%
下载:77%
下载:78%
下载:79%
下载:80%
下载:81%
下载:82%
下载:83%
下载:84%
下载:85%
下载:85%
下载:86%
下载:87%
下载:88%
下载:89%
下载:90%
下载:91%
下载:92%
下载:93%
下载:94%
下载:95%
下载:95%
下载:96%
下载:97%
下载:98%
下载:99%
下载:100%

ie81com 发表于 2023-1-18 16:32

这个貌似是服务器问题吧,没有实时返回进度

ie81com 发表于 2023-1-18 16:37

ilovecomputer66 发表于 2023-1-18 15:18
非常感谢。但是,发现上传进度不太对
把回调函数改为打印,结果如下



搜到一篇,供你参考。。
//zhuanlan.zhihu.com/p/23757396

ilovecomputer66 发表于 2023-1-18 18:08

感谢 ie81com

ilovecomputer66 发表于 2023-1-19 16:32

ie81com 发表于 2023-1-18 16:37
搜到一篇,供你参考。。
//zhuanlan.zhihu.com/p/23757396

@ie81com

我找到了个解决方案,上传速度也可以很精确http://cn.voidcc.com/question/p-yzihfdcl-hs.html

但还想请教下兄弟,就之前我那个同步的写法,究竟为什么如果用到ProgressMessageHandler,就会卡死呢?如果请求不是异步执行的,为什么又对ProgressMessageHandler产生影响,进而导致整个程序永远卡死呢
页: [1] 2
查看完整版本: C#内置HttpClient发Multipart请求上传时以及等待服务器处理完上传的下载中,进度怎知?