c# http

C#代码
客户端:

NETCore提供了三种不同类型用于生产的REST API: HttpWebRequest;WebClient;HttpClient

HttpWebRequest

这是.NET创建者最初开发用于使用HTTP请求的标准类。使用HttpWebRequest可以让开发者控制请求/响应流程的各个方面,如 timeouts, cookies, headers, protocols。另一个好处是HttpWebRequest类不会阻塞UI线程。例如,当您从响应很慢的API服务器下载大文件时,您的应用程序的UI不会停止响应。然而,强大的个性化操作带来了极大的复杂性。

主要是使用HttpWebRequest请求使用HttpWebResponse接收响应。

1.使用application/json作为请求头,用来告诉服务端消息主体是序列化的JSON字符串。

/*

*  url:POST请求地址

*  postData:json格式的请求报文,例如:{"key1":"value1","key2":"value2"}

*/

public static string PostUrl(string url, string postData)

{

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);

    req.Method = "POST";

    req.TimeOut = "800";//设置请求超时时间,单位为毫秒

    req.ContentType = "application/json";

    byte[] data = Encoding.UTF8.GetBytes(postData);

    req.ContentLength = data.Length;

    using (Stream reqStream = req.GetRequestStream())

    {

        reqStream.Write(data, 0, data.Length);

        reqStream.Close();

    }

    HttpWebResponse resp = (HttpWebResponse)req.GetResponse();

    Stream stream = resp.GetResponseStream();

    //获取响应内容

    string result = "";

    using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))

    {

        result = reader.ReadToEnd();

}

stream .Close();

 if (resp != null)

 {

    resp .Close();

  }

 if (req!= null)

 {

    req.Abort();

 }

    return result;

}

2.使用multipart/form-data作为请求头,用来告诉服务器消息主体是 多发文件 格式。

/// <summary>

/// 上传文件请求

/// </summary>

/// <param name="url">Url</param>

/// <param name="filePath">文件路径</param>

/// <param name="formDatas">表单数据(字典格式)</param>

/// <param name="callback">上传回调</param>

public static void UploadRequest(string url, string filePath, Dictionary<string,string> formDatas, Action<string> callback)

{

    // 时间戳,用做boundary

    string timeStamp = DateTime.Now.Ticks.ToString("x");

    //根据uri创建HttpWebRequest对象

    HttpWebRequest httpReq = (HttpWebRequest) WebRequest.Create(new Uri(url));

    httpReq.Method = "POST";

    httpReq.AllowWriteStreamBuffering = false; //对发送的数据不使用缓存

    httpReq.Timeout = 300000; //设置获得响应的超时时间(300秒)

    httpReq.ContentType = "multipart/form-data; boundary=" + timeStamp;

    //读取file文件

    FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);

    BinaryReader binaryReader = new BinaryReader(fileStream);

    

    //表单信息

    string boundary = "--" + timeStamp;

    string form = "";

    string formFormat = boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n";

    string formEnd = boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type:application/octet-stream\r\n\r\n";

    foreach (var pair in formDatas)

    {

        form += string.Format(formFormat, pair.Key, pair.Value);

    }

    form += string.Format(formEnd,"file", Path.GetFileName(filePath));

    byte[] postHeaderBytes = Encoding.UTF8.GetBytes(form);

    //结束边界

    byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + timeStamp + "--\r\n");

    long length = fileStream.Length + postHeaderBytes.Length + boundaryBytes.Length;

    httpReq.ContentLength = length; //请求内容长度

    try

    {

        //每次上传4k

        int bufferLength = 4096;

        byte[] buffer = new byte[bufferLength];

        //已上传的字节数

        long offset = 0;

        int size = binaryReader.Read(buffer, 0, bufferLength);

        Stream postStream = httpReq.GetRequestStream();

        //发送请求头部消息

        postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);

        while (size > 0)

        {

            postStream.Write(buffer, 0, size);

            offset += size;

            size = binaryReader.Read(buffer, 0, bufferLength);

        }

        //添加尾部边界

        postStream.Write(boundaryBytes, 0, boundaryBytes.Length);

        postStream.Close();

        //获取服务器端的响应

        using (HttpWebResponse response = (HttpWebResponse) httpReq.GetResponse())

        {

            Stream receiveStream = response.GetResponseStream();

            StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

            string returnValue = readStream.ReadToEnd();

            Debug.Log("upload result:"+returnValue);

            callback?.Invoke(returnValue);

            

            response.Close();

            readStream.Close();

        }

    }

    catch (Exception ex)

    {

        Debug.Log("文件传输异常: " + ex.Message);

    }

    finally

    {

        fileStream.Close();

        binaryReader.Close();

    }

}

  1. 使用multipart/form-data作为请求头 自己写的例子

Content-Type: multipart/form-data; boundary=AaB03x

 --AaB03x

 Content-Disposition: form-data; name="submit-name1"

 Larry1

 --AaB03x

 Content-Disposition: form-data; name="submit-name2"

 Larry2

 --AaB03x--

格式

  1. Content-Type: multipart/form-data; boundary=AaB03x

首先声明数据类型为multipart/form-data, 然后定义边界字符串AaB03x,这个边界字符串就是用来在下面来区分各个数据的,可以随便定义,但是最好是用破折号等数据中一般不会出现的字符。然后是换行符。

  1. --AaB03x

这个是边界字符串,注意每一个边界符前面都需要加2个连字符“--”,然后跟上换行符。

  1. Content-Disposition: form-data; name="submit-name"

这里是Key-Value数据中字符串类型的数据。 submit-name 是这个Key-Value数据中的Key。当然也需要换行符。

  1. Larry1

这个就是刚才Key-Value数据中的value。

  1. --AaB03x

边界符,表示数据结束。

  1. --AaB03x--

数据结束后的分界符,注意因为这个后面没有数据了所以需要在后面追加一个“--”表示结束。

public static string GetToken(string strUrl, Dictionary<string, string> kVDatas)

        {

            string strtoken = "";

            if (string.IsNullOrEmpty(strUrl) || kVDatas.Count <= 0)

            {

                string strTip = "获取token的参数为空,请设置配置文件的url、uid、sid.";

                Logger.WriteError(strTip);

                return "";

            }

            try

            {

                string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");

                byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");

                byte[] endbytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");

                //1.HttpWebRequest

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strUrl);

                request.ContentType = "multipart/form-data; boundary=" + boundary;

                request.Method = "POST";

                request.KeepAlive = true;

                request.Timeout = s_nLinkTime*1000;

                CredentialCache credentialCache = new CredentialCache();

                credentialCache.Add(new Uri(strUrl), "Basic", new NetworkCredential("member", "secret"));

                request.Credentials = credentialCache;

                request.ServicePoint.Expect100Continue = false;

                using (Stream stream = request.GetRequestStream())

                {

                    //1.1 key/value

                    string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";

                    if (kVDatas != null)

                    {

                        foreach (string key in kVDatas.Keys)

                        {

                            stream.Write(boundarybytes, 0, boundarybytes.Length);

                            string formitem = string.Format(formdataTemplate, key, kVDatas[key]);

                            byte[] formitembytes = Encoding.GetEncoding("UTF-8").GetBytes(formitem);

                            stream.Write(formitembytes, 0, formitembytes.Length);

                        }

                    }

                    stream.Write(endbytes, 0, endbytes.Length);

                    //stream.Close();//已通过using 自动释放,不需要手动释放资源

                }

                //2.WebResponse

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                using (StreamReader stream = new StreamReader(response.GetResponseStream()))

                {

                    string strRecvData = stream.ReadToEnd();

                    JObject obj = (JObject)JsonConvert.DeserializeObject(strRecvData);//将刚才一大串字符串转换成一个大对象

                    string strSuc = obj["success"].ToString();

                    if (strSuc.Equals("true", StringComparison.OrdinalIgnoreCase))

                    {

                        strtoken = obj["data"]["token"].ToString();

                    }

                    //stream.Close();//已通过using 自动释放,不需要手动释放资源

                }

               

                if (request != null)

                {

                    request.Abort();

                }

                if (response != null)

                {

                    response.Close();

                }

            }

            catch (Exception e)

            {

                Logger.WriteError("获取token" + e.Message);

                return "";

            }

            return strtoken;

        }

WebClient:

WebClient一种更高级别的抽象,是HttpWebRequest为了简化最常见任务而创建的,使用过程中你会发现他缺少基本的header,timeoust的设置,不过这些可以通过继承httpwebrequest来实现。相对来说,WebClient比WebRequest更加简单,它相当于封装了request和response方法,不过需要说明的是,Webclient和WebRequest继承的是不同类,两者在继承上没有任何关系。

using (WebClient webClient = new WebClient())

   {

       webClient.DownloadFile("http://example.com", "路径");

   }

HttpClient

HttpClient是.NET4.5引入的一个HTTP客户端库,其命名空间为 System.Net.Http ,.NET 4.5之前我们可能使用WebClient和HttpWebRequest来达到相同目的。HttpClient利用了最新的面向任务模式,使得处理异步请求非常容易。它适合用于多次请求操作,一般设置好默认头部后,可以进行重复多次的请求,基本上用一个实例可以提交任何的HTTP请求。HttpClient有预热机制,第一次进行访问时比较慢,所以不应该用到HttpClient就new一个出来,应该使用单例或其他方式获取HttpClient的实例。

public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption);

public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content);

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request);//允许发送任何类型的HTTP请求(GET、POST、PUT、DELETE等),并且可以完全控制请求的各个方面(如URL、头部、内容等

HttpRequestMessage类:表示用户请求消息;

public HttpContent Content { get; set; } //请求报文内容

Public HttpMethod Method { get; set; } //方法

public Uri RequestUri { get; set; }  //url

public HttpRequestHeaders Headers { get; } //请求头

HttpResponseMessage类:表示http响应消息;

public HttpContent Content { get; set; }  //响应的协议内容

public HttpStatusCode StatusCode { get; set; }响应的状态码

Public HttpRequestMessage RequestMessage { get; set; }请求信息

public HttpResponseHeaders Headers { get; } 响应头

HttpContent 类型用于表示 HTTP 实体正文和相应的内容标头。

public Task<string> ReadAsStringAsync();

public StringContent(string content, Encoding encoding);

Object<-HttpContent<-ByteArrayContent

1.StringContent(字符串)基于字符串提供 HTTP 内容 用于application/json

2.FormUrlEncodedContent 键值对  用于application/x-www-form-urlencoded

3.MultipartFormDataContent 用于  multipart/form-data

通过Get请求数据

var httpClient = new HttpClient();

var url = "http://localhost:9000/index.html";

var response = await httpClient.GetAsync(url);

var str = await response.Content.ReadAsStringAsync();

通过Post请求数据: application/x-www-form-urlencoded

var httpClient = new HttpClient();

var url = "http://192.168.0.9:9000/Demo/PostUrlCode";

var response = await httpClient.PostAsync(url, new FormUrlEncodedContent(new List<KeyValuePair<string, string>>()

{

    new KeyValuePair<string, string>("name","小明"),

    new KeyValuePair<string, string>("age","20")

}));

var str = await response.Content.ReadAsStringAsync();

上面的请求报文:

POST /Demo/PostUrlCode HTTP/1.1

Host: 192.168.0.9:9000

Content-Type: application/x-www-form-urlencoded

Content-Length: 30

name=%E5%B0%8F%E6%98%8E&age=20

使用Post请求数据:application/json

var httpClient = new HttpClient();

var url = "http://192.168.0.9:9000/Demo/PostUrlJson"

var response = await httpClient.PostAsync(

    url,

    new StringContent(

        Newtonsoft.Json.JsonConvert.SerializeObject(new { Name = "小明", Id = 1 }),

        Encoding.UTF8,

        "application/json")

    );

var str = await response.Content.ReadAsStringAsync();

POST /Demo/PostUrlJson HTTP/1.1

Host: 192.168.0.9:9000

Content-Type: application/json; charset=utf-8

Content-Length: 24

完整例子

        static HttpClient httpClient = new HttpClient();

        //获取token

        public async Task<string> GetToken(string strUrl, Dictionary<string, string> kVDatas)

        {

            string strToken = "";

            if (string.IsNullOrEmpty(strUrl))

            {

                string strTip = "获取token的参数为空,请设置配置文件的url。";

                Logger.WriteError(strTip);

                return "";

            }

            string strRequestData = JsonConvert.SerializeObject(kVDatas);

            try

            {

                var request = new HttpRequestMessage();

                request.Method = HttpMethod.Post;

                request.RequestUri = new Uri(strUrl);

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

                // 添加自定义请求头

                //request.Headers.Add("X-Custom-Header", "value");

                var response = await httpClient.SendAsync(request);

                string strRecvData = await response.Content.ReadAsStringAsync();

                JObject obj = (JObject)JsonConvert.DeserializeObject(strRecvData);//将刚才一大串字符串转换成一个大对象

                int nCode = Convert.ToInt32(obj["code"]);

                if (nCode == 1000)

                {

                    strToken = obj["data"]["token"].ToString();

                }

            }

            catch (Exception e)

            {

                Logger.WriteError("获取token" + e.Message);

                return "";

            }

            return strToken;

        }

{"Name":"小明","Id":1}

通过Post上传文件:multipart/form-data

var httpClient = new HttpClient();

var url = "http://localhost:9000/Demo/PostMulti";

var content = new MultipartFormDataContent();

content.Add(new StringContent("小明"), "name");

content.Add(new StringContent("18"), "age");

//注意:要指定filename,即:test.txt,否则后台不认为是一个文件,而是普通的参数

content.Add(new ByteArrayContent(System.IO.File.ReadAllBytes("e:\\test.txt")), "file", "test.txt");

var response = await httpClient.PostAsync(url, content);

var str = await response.Content.ReadAsStringAsync();

产生的请求报文如下:

POST /Demo/PostMulti HTTP/1.1

Host: 192.168.0.9:9000

Content-Type: multipart/form-data; boundary="ecc429f8-1f51-43a6-af5b-0fc8a88da513"

Content-Length: 451

--ecc429f8-1f51-43a6-af5b-0fc8a88da513

Content-Type: text/plain; charset=utf-8

Content-Disposition: form-data; name=name

小明

--ecc429f8-1f51-43a6-af5b-0fc8a88da513

Content-Type: text/plain; charset=utf-8

Content-Disposition: form-data; name=age

18

--ecc429f8-1f51-43a6-af5b-0fc8a88da513

Content-Disposition: form-data; name=file; filename=test.txt; filename*=utf-8''test.txt

this is file.

--ecc429f8-1f51-43a6-af5b-0fc8a88da513--

 //使用HttpClient 对应后面GetToken一样的效果

        public static async Task<string>  GetTokenname(string strUrl, Dictionary<string, string> kVDatas)

        {

            string strtoken = "";

            try

            {

                var content = new MultipartFormDataContent();

                foreach (string key in kVDatas.Keys)

                {

                    content.Add(new StringContent(kVDatas[key]), key);

                }

                using (var httpClient = new HttpClient())

                {

                    using (HttpResponseMessage response = await httpClient.PostAsync(strUrl, content))

                    {

                        if (response.IsSuccessStatusCode)

                        {

                            var str = await response.Content.ReadAsStringAsync();

                            JObject obj = (JObject)JsonConvert.DeserializeObject(str);//将刚才一大串字符串转换成一个大对象

                            string strSuc = obj["success"].ToString();

                            if (strSuc.Equals("true", StringComparison.OrdinalIgnoreCase))

                            {

                                strtoken = obj["data"]["token"].ToString();

                            }

                        }

                    }

                }

            }

            catch (Exception e)

            {

                Logger.WriteError("获取token" + e.Message);

                return "";

            }   

            return strtoken;

        }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/69570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

哈希表实现(C++实现)

目录 1.哈希概念 2.哈希冲突 3.哈希函数 4.哈希冲突解决 闭散列 —— 开放定址法 线性探测 二次探测 开散列 —— 链地址法&#xff08;拉链法、哈希桶&#xff09; 5.哈希表的闭散列实现 哈希表的结构 哈希表的大小和扩容 哈希表的插入 哈希表的查找 哈希表的删除…

开箱即用:一个易用的开源表单工具!

随着互联网的普及&#xff0c;表单应用场景越来越广泛&#xff0c;从网站注册、调查问卷到考试测评&#xff0c;无处不在。传统的表单制作方式需要一定的代码基础&#xff0c;对于不懂编程的小伙伴来说&#xff0c;无疑是一道门槛。 今天&#xff0c;给大家分享一款开源的表单…

牛客 BM1: 反转链表

目录 一、题目 二、C解题程序框架 1. 结构体定义 2. 类定义 3. 输入输出说明 三、链表指针 1. 链表指针的基本概念 2. 链表指针的常见操作 1. 遍历链表 2. 插入节点 3. 删除节点 3. 链表指针操作的注意事项 4. 总结 四、解题 方法一&#xff1a;迭代法 方法二&…

MIT开源7B推理模型Satori:用行动思维链进行强化学习,增强自回归搜索

自OpenAI的o1发布以来&#xff0c;研究社区为提升开源LLM的高级推理能力做出了诸多努力&#xff0c;包括使用强大的教师模型进行蒸馏、蒙特卡洛树搜索&#xff08;MCTS&#xff09;以及基于奖励模型的引导搜索等方法。 本研究旨在探索一个新的研究方向&#xff1a;使LLM具备自回…

Kubernetes控制平面组件:etcd(一)

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;kubectl 和 …

Express 中间件

在构建 Web 应用程序时&#xff0c;中间件&#xff08;Middleware&#xff09;扮演着至关重要的角色。它允许你定义一系列的函数来处理 HTTP 请求和响应过程中的各种任务。Express.js 是 Node.js 上最流行的框架之一&#xff0c;以其简洁且强大的中间件机制著称。本文将深入探讨…

Django在终端创建项目(pycharm Windows)

1.选择目录 选择或新建一个文件夹&#xff0c;作为项目保存的地方 2.右键在终端打开 3.确定django-admin.exe安装位置 找到自己安装django时&#xff0c;django-admin.exe安装的位置&#xff0c;例如 4.运行命令 使用django-admin.exe的绝对路径&#xff0c;在刚才打开的终端…

Android 常用设计模式和实例

一、什么是设计模式&#xff1f; 设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问&#xff0c;设计模式于己于他人于系统都是多赢的&#xff0c;设计模式使代码编制真正工程化&#xff0c;设计模式是软件工程的基石&#xff0c;如同大厦的一块块…

跨平台开发利器:UniApp 全面解析与实践指南

文章目录 一、UniApp 是什么&#xff1f;核心优势&#xff1a; 二、核心特性解析1. 跨端原理2. 技术架构3. 主要功能特性 三、开发环境搭建1. 必备工具2. 项目创建3. 目录结构 四、开发实践指南1. 页面开发示例2. 跨端API调用3. 条件编译实战 五、性能优化技巧1. 启动速度优化2…

e2studio开发RA2E1(9)----定时器GPT配置输入捕获

e2studio开发RA2E1.9--定时器GPT配置输入捕获 概述视频教学样品申请硬件准备参考程序源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置UART配置UART属性配置设置e2studio堆栈e2studio的重定向printf设置R_SCI_UART_Open()函数原型回调函数user_uart_callback…

【Java】MyBatis动态SQL

在MyBatis中使用动态SQL语句。 动态SQL是指根据参数数据动态组织SQL的技术。 生活中的案例&#xff1a; 在京东上买东西时&#xff0c;用户搜索商品&#xff0c;可以选择筛选条件&#xff0c;比如品牌&#xff0c;价格&#xff0c;材质等&#xff0c;也可以不使用筛选条件。这时…

【PS 2022】Adobe Genuine Service Alert 弹出

电脑总是弹出Adobe Genuine Service Alert弹窗 1. 不关掉弹窗并打开任务管理器&#xff0c;找到Adobe Genuine Service Alert&#xff0c;并右键进入文件所在位置 2 在任务管理器中结束进程并将文件夹中的 .exe 文件都使用空文档替换掉 3. 打开PS不弹出弹窗&#xff0c;解决&a…

RoboGrasp:一种用于稳健机器人控制的通用抓取策略

25年1月来自北京大学和哈佛大学的论文“RoboGrasp: A Universal Grasping Policy for Robust Robotic Control”。 模仿学习和世界模型在推进通用机器人学习方面显示出巨大的潜力&#xff0c;而机器人抓取仍然是实现精确操控的关键挑战。现有方法通常严重依赖机械臂状态数据和…

接口测试Day12-持续集成、git简介和安装、Gitee远程仓库、jenkins集成

持续集成 概念&#xff1a; 团队成员将自己的工作成果&#xff0c;持续集成到一个公共平台的过程。成员可以每天集成一次&#xff0c;也可以一天集成多 次。 相关工具&#xff1a; 本地代码管理&#xff1a;git远程代码管理&#xff1a;gitee(国内)、github(国外)、gitlib(公司…

pytest测试专题 - 1.1 运行pytest

<< 返回目录 1 pytest学习笔记 - 1.1 运行pytest 1.1 运行pyest 在命令行执行pytest --help usage: pytest [options] [file_or_dir] [file_or_dir] [...] ... ...1.1.1 pytest不携带参数 pytest不带参数时&#xff0c;会扫描当前目录下的所有目录、子目录中符合测试用…

Django REST Framework:如何获取序列化后的ID

Django REST Framework&#xff1a;如何获取序列化后的ID &#x1f604; 嗨&#xff0c;小伙伴们&#xff01;今天我们来聊一聊Django REST Framework&#xff08;简称DRF&#xff09;中一个非常常见的操作&#xff1a;如何获取序列化后的ID。对于那些刚入门的朋友们&#xff…

C语言基础11:分支结构以及if的使用

C语言基础 内容提要 分支结构 条件判断用if语句实现分支结构 分支结构 问题抛出 我们在程序设计往往会遇到如下问题&#xff0c;比如下面的函数的计算&#xff1a; y { 1 / x 当 x ≠ 0 时 10000 当 x 0 时 y \begin{cases} 1/x \quad当x\neq0时\\ \\ 10000 \quad当x0…

利用navicat 17 实现两个不同数据库oracle和sqlserver2008之间多个表数据的自动同步

要实现两个不同数据库&#xff08;Oracle 和 SQL Server 2008&#xff09;之间多个表数据的自动同步&#xff0c;可以利用 Navicat 17 的“数据传输”功能&#xff08;Data Transfer&#xff09;和“任务调度”功能&#xff08;Task Scheduler&#xff09;。下面是一个概括的步…

81页精品PPT | 华为流程与信息化实践与架构规划分享

华为流程与信息化实践与架构规划分享主要围绕华为在业务流程与信息化建设方面的经验、企业架构规划方法以及企业数字化转型路径展开。华为通过持续的业务变革和信息化建设&#xff0c;从本土企业逐步发展为国际化、全球化企业&#xff0c;其管理体系以持续创新和世界级管理体系…

智能客服API接口:提升电商平台用户体验的新途径

在数字化时代&#xff0c;电商平台已成为人们购物的主要渠道之一。随着用户需求的日益多样化和个性化&#xff0c;电商平台面临着前所未有的挑战&#xff0c;即如何在激烈的市场竞争中脱颖而出&#xff0c;提供卓越的用户体验。智能客服API接口作为连接电商平台与智能客服系统的…