WPS本地镜像化在线文档操作以及样例

一个客户项目有引进在线文档操作需求,让我这边做一个demo调研下,给我的对接文档里有相关方法的说明,照着对接即可。但在真正对接过程中还是踩过不少坑,这儿对之前的对接工作做个记录。
按照习惯先来一个效果:

 Demo下载链接:https://download.csdn.net/download/qxyywy/88117444

接入指引


1. 申请授权证书并进行授权。
2. 登录系统后台页面
3. 创建、获取应用信息 access_key (简称ak)、 secret_key (简称 sk )。开发者在接口调用时,使用ak 、 sk 生成WPS-4签名进行鉴权。
4. 在线编辑、在线预览、格式转换接入按照对应开放能力文档接入。在线编辑、在线预览对接过程中需要设置回调地址。其中,在线编辑可通过配置开启历史版本功能。
5. 使用过程中需通过证书查询接口关注授权证书状态,若证书即将过期或者不可用,需进行更新证书操作。
6. 在线编辑或在线预览服务端对接完毕,对接方可使用JSSDK,调用API实现相关需求。

WPS-4签名算法

在对接时,耗费了一定时间在WPS-4签名处,对接文档中有WPS-4的说明和样例,自己在对接转换成NetCore的时候踩了一些坑,签名算法中最主要是:Wps-Docs-Authorization的计算方法
签名格式:WPS-4 {accessKey}:{signature}  注意WPS-4后面有空格。
signature:hmac-sha256(secret_key, Ver + HttpMethod + URI + Content-Type + WpsDocs-Date + sha256(HttpBody))
signature的样例如下:WPS-4POST/callback/path/demoapplication/jsonWed, 20 Apr 2022 01:33:07GMTfc005f51a6e75586d2d5d078b657dxxxdf9c1dfa6a7c0c0ba38c715daeb6ede9

这是文档中对签名算法的解释,对照着格式完成相关算法,具体算法如下:
signature的组装:

        /// <summary>
        /// 获取签名
        /// </summary>
        /// <param name="method">请求方法,如:GET,POST</param>
        /// <param name="uri">请求url,带querystring</param>
        /// <param name="body">请求body</param>
        /// <param name="date">日期</param>
        /// <param name="contentType">默认:application/json</param>
        /// <param name="secretKey">应用SK</param>
        /// <returns></returns>
        public static string WPS4Signature(string secretKey,string method,string uri, byte[] body=null,DateTime? date=null,string contentType= "application/json")
        {
            //获取uri路径
            string path = uri;
            //日期格式化
            if (date == null)
                date = DateTime.Now;
            string dateStr = String.Format("{0:r}", date);
            //open不参与签名,做替换处理
            if (path.StartsWith("/open"))
            {
                path = path.Replace("/open", "");
            }

            string sha256body;
            //body为空则为空,否则返回sha256(body)
            if (body != null && body.Length > 0)
            {
                sha256body = Sha256(body);
            }
            else
            {
                sha256body = "";
            }
            String signature = null;
            signature = HmacSHA256Encrypt($"WPS-4{method.ToUpper()}{path}{contentType}{dateStr}{sha256body}", secretKey);

            return signature;
        }

HmacSHA256加密算法:

        /// <summary>
        /// HmacSHA256加密
        /// </summary>
        /// <param name="secret"></param>
        /// <param name="signKey"></param>
        /// <returns></returns>
        public static string HmacSHA256Encrypt(string secret, string signKey)
        {
            string signRet = string.Empty;
            using (HMACSHA256 mac = new HMACSHA256(Encoding.UTF8.GetBytes(signKey)))
            {
                byte[] hash = mac.ComputeHash(Encoding.UTF8.GetBytes(secret));
                //signRet = Convert.ToBase64String(hash);
                signRet = ToHexStrFromByte(hash); 
            }
            return signRet;
        }

Sha256转换:

        /// <summary>
        /// Sha256转换
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns>A hash.</returns>
        public static string Sha256(this byte[] input)
        {
            if (input == null)
            {
                return null;
            }
            using (var sha = SHA256.Create())
            {
                var hash = sha.ComputeHash(input);
                return ToHexStrFromByte(hash);
            }
        }

字节数组转16进制字符串:

        /// <summary>
        /// 字节数组转16进制字符串:空格分隔
        /// </summary>
        /// <param name="byteDatas"></param>
        /// <returns></returns>
        public static string ToHexStrFromByte(this byte[] byteDatas)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < byteDatas.Length; i++)
            {
                builder.Append(string.Format("{0:X2}", byteDatas[i]));
            }
            return builder.ToString().Trim().ToLower();
        }

获取在线预览链接

        /// <summary>
        /// 获取在线预览链接
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/wps/previewgenarate")]
        [HttpPost]
        public Task<GenarateResult> GenarateWPSPreviewUrl(GenarateRequest request)
        {
            return Task.Run(() =>
            {
                string wpsHost = "http://10.4.**.**";
                string uri = $"/api/preview/v1/files/{defaultFileId}/link?type=w&preview_mode=high_definition";
                string fullUrl = $"{wpsHost}/open{uri}";
                Dictionary<string, string> headers = new Dictionary<string, string>();
                DateTime now = DateTime.Now;
                headers.Add("Content-Type", "application/json");
                headers.Add("Wps-Docs-Date", String.Format("{0:r}", now));
                var signature = WPSLocalSIgnatureHelper.WPS4Signature("SKrpaxjdwoetijjv", "get", uri, null, now);
                string docsAuthorization = WPSLocalSIgnatureHelper.WPS4SignAuthorization("UOMYPEVAHWQLTKJF", signature);
                headers.Add("Wps-Docs-Authorization", docsAuthorization);
                HttpHelper httpHelper = new HttpHelper();
                var resultTemp = httpHelper.Get(fullUrl, headers);
                var result = JsonConvert.DeserializeObject<ResponseBaseModel<OnlineEditResultModel>>(resultTemp);
                string url = "";
                if (result != null && result.data != null)
                {
                    url = result.data.link;
                }
                return new GenarateResult { Url = url };
            });
        }

这儿比较坑的地方来了,方法参数都组装好了,通过HttpWebRequest后端发起请求获取WPS中台返回的在线预览地址时,始终提示401报错获取不到数据。迫不得已自己通过APIPost组装了相关请求和参数居然又能获取到相关数据。对照了下请求头,又差异后调整了程序的请求头,保证和apiPost里的完全一致,依然返回401,通过查阅相关资料找到一个处理办法,在发起的请求后手动捕获WebException,然后在WebException里解析数据流获取信息。
HttpWebRequest Get方式访问
 

        /// <summary>
        ///  Get方式访问
        /// </summary>
        /// <param name="url"></param>
        /// <param name="encode"></param>
        /// <param name="referer"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public string Get(string url, string encode, string referer, Dictionary<string, string> headers=null)
        {
            int num = _tryTimes;
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            StreamReader reader = null;
            while (num-- >= 0)
            {
                try
                {
                    DelaySomeTime();
                    ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);//验证服务器证书回调自动验证
                    request = (HttpWebRequest)WebRequest.Create(url);
                    request.Headers.Add("accept", "*/*");
                    request.Headers.Add("accept-encoding", "gzip, deflate, br");
                    request.Headers.Add("accept-language", "zh-CN");
                    request.Headers.Add("connection", "keep-alive");
                    
                    if (headers != null) 
                    {
                        foreach (var item in headers)
                        {
                            request.Headers.Add(item.Key, item.Value);
                        }
                    }
                    //request.UserAgent = reqUserAgent;
                    request.CookieContainer = _cookie;
                    request.Referer = referer;
                    request.Method = "GET";
                    request.Timeout = _timeOut;
                    if (_proxy != null && _proxy.Credentials != null)
                    {
                        request.UseDefaultCredentials = true;
                    }
                    request.Proxy = _proxy;
                    response = (HttpWebResponse)request.GetResponse();
                    reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encode));
                    return reader.ReadToEnd();
                }
                catch (WebException ex)
                {
                    response = (HttpWebResponse)ex.Response; //解析401等错误返回的有效信息
                    var resultTemp = "";
                    Stream stream = response.GetResponseStream();
                    using (StreamReader readers = new StreamReader(stream, Encoding.UTF8))
                    {
                        resultTemp = readers.ReadToEnd();
                    }
                    return resultTemp;
                }
                catch (Exception ex)
                {
                    _logger.Error(url + "\r\n" + ex.ToString());
                    continue;
                }
                finally
                {
                    if (request != null)
                    {
                        request.Abort();
                    }
                    if (response != null)
                    {
                        response.Close();
                    }
                    if (reader != null)
                    {
                        reader.Close();
                    }
                }
            }
            return string.Empty;
        }

DemoHtml


到上面时后端的处理就基本完成,前端这边因为时临时demo就用了一个html来处理,真实项目中需要用VUE等处理也都类似。
以下为 html的代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <!-- 建议禁用外框浏览器自带的缩放 -->
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no"
        />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>WPS Web Office(iframe)接入指南</title>
        <style>
            * {
                box-sizing: border-box;
            }

            html,
            body {
                display: flex;
                flex-direction: column;
                padding: 0;
                margin: 0;
                height: 100%;
                /* 防止双击缩放 */
                touch-action: manipulation;
            }

            iframe {
                flex: 1;
            }
        </style>
        <!-- cdn引入JQ -->
        <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>
        <script src="./jwps.js"></script>
        <script type="text/javascript">
            var appHost = "http://10.4.146.19:8890";
            // 支持 HTTPS
            // 注意:如果通过postMessage来设置token,请在url参数加上_w_tokentype=1
            function showWPS(url) {
                // 初始化
                var wps = WPS.config({
                    mount: document.querySelector("#wpsPanl"),
                    // 文字
                    wpsUrl: url,
                    headers: {
                        shareBtn: {
                            tooltip: "分享",
                            subscribe: function() {
                                console.log("click callback");
                            }
                        },
                        otherMenuBtn: {
                            tooltip: "其他按钮",
                            items: [
                                {
                                    // 自定义, type 固定填 'custom'
                                    type: "custom",
                                    icon:
                                        "http://ep.wps.cn/index/images/logo_white2.png",
                                    text: "API 导出 PDF",
                                    subscribe: function(wps) {
                                        if (wps.WpsApplication) {
                                            wps.WpsApplication()
                                                .ActiveDocument.ExportAsFixedFormatAsync()
                                                .then(function(result) {
                                                    console.table(result);
                                                });
                                        }
                                    }
                                },
                                {
                                    // 自定义, type 固定填 'custom'
                                    type: "custom",
                                    icon:
                                        "http://ep.wps.cn/index/images/logo_white2.png",
                                    text: "API 使用",
                                    subscribe: function(wps) {
                                        let result;
                                        if (wps.WpsApplication) {
                                            wps.WpsApplication()
                                                .ActiveDocument.ExportAsFixedFormatAsync()
                                                .then(function(result) {
                                                    console.table(result);
                                                });
                                        }
                                    }
                                }
                            ]
                        }
                    }
                });
                return wps;
            }

            window.onload = function() {
                 $.ajax({
                    url: appHost+"/api/wps/previewgenarate",
                    contentType: "application/json",
                    dataType: "json",
                    data: JSON.stringify({
                        fileId: 'a123',
                        fileName: "test.docx",
                        fileType: 1,
                        userId: 1505340867
                    }),
                    type: "post",
                    success: function(res) {
                        var wpsUrl = res.url;
                        console.log(wpsUrl);
                        var wps = showWPS(wpsUrl);
                    }
                 });

                var fileInput = document.getElementById("bookimg1");
                //选择文件
                fileInput.addEventListener('change', function () {
                    //如果未传入文件则中断
                    if (fileInput.files[0] == undefined) {
                        return;
                    }

                    var file = fileInput.files[0];

                    //FileReader可直接将上传文件转化为二进制流
                    var reader = new FileReader();
                    reader.readAsDataURL(file);//转化二进制流,异步方法
                    reader.onload = function (result) {//完成后this.result为二进制流
                        var base64Str = this.result;
                        $('#uploadImg').attr('src', base64Str);
                        $('#imgPreview').show();
                    } 
                })
            };
            function replaceWps() {
                $('.tdname1').html($('#name1').val());
                $('.tddept1').html($('#dept1').val());
                $('.tdage1').html($('#age1').val());
                $('.tdname2').html($('#name2').val());
                $('.tddept2').html($('#dept2').val());
                $('.tdage2').html($('#age2').val());
                var fileBytes = "";
                var fileName = "";
                if ($('#bookimg1')[0].files[0] != undefined) {
                    var imgFile = $('#bookimg1')[0].files[0];
                    fileName = imgFile.name;
                    //FileReader可直接将上传文件转化为二进制流
                    var reader = new FileReader();
                    reader.readAsDataURL(imgFile);//转化二进制流,异步方法
                    reader.onload = function (result) {//完成后this.result为二进制流
                        var base64Str = this.result;
                        var startNum = base64Str.indexOf("base64,");
                        startNum = startNum * 1 + 7;
                        //去除前部格式信息(如果有需求)
                        var baseStr = base64Str.slice(startNum);
                        fileBytes = baseStr;

                        $.ajax({
                            url: appHost + "/api/wps/wrapheader",
                            contentType: "application/json",
                            dataType: "json",
                            data: JSON.stringify({
                                sample_list: [
                                    {
                                        bookmark: 'bookmark1',
                                        type: 'TEXT',
                                        text: $('#bookmark1').val()
                                    },
                                    {
                                        bookmark: 'bookmark2',
                                        type: 'TEXT',
                                        text: $('#bookmark2').val()
                                    },
                                    {
                                        bookmark: 'bookmark3',
                                        type: 'TEXT',
                                        text: $('#bookmark3').val()
                                    },
                                    {
                                        bookmark: 'bookimg1',
                                        type: 'IMAGE',
                                        /*sample_url:$('#bookimg1').val(),*/
                                        sample_filename: fileName,
                                        text: fileBytes,
                                    },
                                    {
                                        bookmark: 'bookform1',
                                        type: 'TEXT',
                                        text: $('#testForm').prop("outerHTML")
                                    }
                                ],
                            }),
                            type: "post",
                            success: function (res) {
                                var wpsUrl = res.url;;
                                var wps = showWPS(wpsUrl);
                            }
                        });
                    }
                } else {
                    $.ajax({
                        url: "http://10.4.146.19:8890/api/wps/wrapheader",
                        contentType: "application/json",
                        dataType: "json",
                        data: JSON.stringify({
                            sample_list: [
                                {
                                    bookmark: 'bookmark1',
                                    type: 'TEXT',
                                    text: $('#bookmark1').val()
                                },
                                {
                                    bookmark: 'bookmark2',
                                    type: 'TEXT',
                                    text: $('#bookmark2').val()
                                },
                                {
                                    bookmark: 'bookmark3',
                                    type: 'TEXT',
                                    text: $('#bookmark3').val()
                                },
                                {
                                    bookmark: 'bookform1',
                                    type: 'TEXT',
                                    text: $('#testForm').prop("outerHTML")
                                }
                            ],
                        }),
                        type: "post",
                        success: function (res) {
                            var wpsUrl = res.url;;
                            var wps = showWPS(wpsUrl);
                        }
                    });
                }

				
			}
        </script>
    </head>
    <body>
		<div style="width:100%;height:700px;">
			<div id="wpsPanl" style="width:65%;float:left;height:100%;"></div>
            <div id="form" style="width:34%;float:left;height:100%;padding-top:50px;padding-left: 20px;">
                <div><div class="title">课题名称:</div><input class="input" type="text" id="bookmark1" placeholder="请填写课题名称"></div>
                <dl style="clear:both;"></dl>
                <div><div class="title">课题申报单位:</div><input class="input" type="text" id="bookmark2" placeholder="请填写课题申报单位"></div>
                <dl style="clear:both;"></dl>
                <div><div class="title">课题负责人:</div><input class="input" type="text" id="bookmark3" placeholder="请填写课题负责人"></div>
                <dl style="clear:both;"></dl>
                <div style="height:140px">
                    <div class="title">课题成员:</div>
                    <table>
                        <thead><tr><td>姓名</td><td>所属部门</td><td>年龄</td></tr></thead>
                        <tr><td><input class="forminput" type="text" id="name1" placeholder="请填写姓名"></td><td><input class="forminput" type="text" id="dept1" placeholder="请填写所属部门"></td><td><input class="forminput" type="text" id="age1" placeholder="请填写年龄"></td></tr>
                        <tr><td><input class="forminput" type="text" id="name2" placeholder="请填写姓名"></td><td><input class="forminput" type="text" id="dept2" placeholder="请填写所属部门"></td><td><input class="forminput" type="text" id="age2" placeholder="请填写年龄"></td></tr>
                    </table>
                    <div style="width:100%;display:none;">
                        <table border="1" cellspacing="0" style="width:90%;" id="testForm">
                            <thead><tr><td>姓名</td><td>所属部门</td><td>年龄</td></tr></thead>
                            <tr><td class="tdname1"></td><td class="tddept1"></td><td class="tdage1"></td></tr>
                            <tr><td class="tdname2"></td><td class="tddept2"></td><td class="tdage2"></td></tr>
                        </table>
                    </div>
                </div>
                <dl style="clear:both;"></dl>
                <div style="height:20px;margin:0;"><div class="title"></div><span style="color:red">表格替换在第6页</span></div>
                <dl style="clear:both;"></dl>
                <div><div class="title">图片上传:</div><input style="padding:8px 0;" type="file" id="bookimg1"></div>
                <div style="display:none;" id="imgPreview"><img src="" id="uploadImg" width="100" /></div>
                <dl style="clear:both;"></dl>
                <div style="height:20px;margin:0;"><div class="title"></div><span style="color:red">图片替换在第7页</span></div>
                <dl style="clear:both;"></dl>
                <div style="text-align:center;">
                    <input style="
    margin: 0 150px;
    height: 40px;
    background: rgba(2,128,204,1);
    border-radius: 2px;
    display: block;
    width: 80px;
    border: none;
    cursor: pointer;
    font-size: 14px;
    font-weight: 600;
    color: rgba(255,255,255,1);
    " type="button" value="替换" onclick="replaceWps()" id="submit">
                </div>
            </div>
		<div>
	</body>
	<style>
		#wpsPanl iframe{width:99%;height:850px;}
		#form div{
			margin: 10px 0;
			height: 40px;
			color: rgba(51,51,51,1);
			float: left;
		}
		#form div .input{
			height: 35px;
			margin: 2px 0;
			width: 358px;
			border: solid 1px rgba(193,193,193,.35);
		}
        #form div .forminput {
            height: 35px;
            margin: 2px 0;
            width: 94px;
            border: solid 1px rgba(193,193,193,.35);
        }
		#form div .title{width:120px;text-align: right;}
        td {
            border: 1px solid rgba(193,193,193,.35);
            padding: 8px 12px;
        }
        tr {
            background-color: inherit;
            font-size: 14px;
            border-top: 1px solid var(--vp-c-divider);
            transition: background-color .5s;
        }
        table {
            /*width: 100%;*/
            display: table;
            border-collapse: collapse;
            /*margin: 20px 0;*/
            overflow-x: auto;
        }
        table thead {
            font-weight: bold;
        }
	</style>
</html>


个人总结:需要在线编辑等相关操作,其实也可以用免费的组件组合,比如可以用onlyoffice+Aspose.Words去操作,仅个人见解。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

K8S系统监控:使用Metrics Server和Prometheus

Kubernetes 也提供了类似的linux top的命令&#xff0c;就是 kubectl top&#xff0c;不过默认情况下这个命令不会生效&#xff0c;必须要安装一个插件 Metrics Server 才可以。 Metrics Server 是一个专门用来收集 Kubernetes 核心资源指标&#xff08;metrics&#xff09;的…

qt服务器 网络聊天室

widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间server new QTcpServer(this); }Widget::~Widget() {delete ui; }//启动…

使用Gradio构建生成式AI应用程序; Stability AI推出Stable Diffusion XL 1.0

&#x1f989; AI新闻 &#x1f680; Stability AI推出最先进的AI工具Stable Diffusion XL 1.0 摘要&#xff1a;Stability AI宣布推出Stable Diffusion XL 1.0&#xff0c;该版本是其迄今为止最先进的AI工具。Stable Diffusion XL 1.0提供更鲜艳、更准确的图片生成&#xff…

【AI之路】使用huggingface_hub优雅解决huggingface大模型下载问题

文章目录 前言一、Hugging face是什么&#xff1f;二、准备工作三、下载整个仓库或单个大模型文件1. 下载整个仓库2. 下载单个大模型文件 总结附录 前言 Hugging face 资源很不错&#xff0c;可是国内下载速度很慢&#xff0c;动则GB的大模型&#xff0c;下载很容易超时&#…

【QT 网络云盘客户端】——主窗口界面的设计

目录 1.设计主窗口界面 2.设置窗口的背景图片 3. 自定义标题栏 3.1 设置toolbutton按钮的图片 3.2 设置按钮的大小 3.3 将自定义标题栏添加设置到主页面中 3.4 去除窗口的原标题栏 3.5 设置按钮颜色 3.6 切换页面功能实现 4.我的文件页面的设计 4.1 菜单栏的设计 4…

分冶算法 剑指 07 重建二叉树 排序算法:剑指45 把数组排成最小的数 10-I 斐波那契数列

来记录几个注意事项 1.vector容器里利用find&#xff08;&#xff09;函数 不同于map&#xff08;map有find方法&#xff09;&#xff0c;vector本身是没有find这一方法&#xff0c;其find是依靠algorithm来实现的。 所以要包含头文件 #include <iostream> #include <…

物联网阀控水表计量准确度如何?

物联网阀控水表是一种新型的智能水表&#xff0c;它采用了先进的物联网技术&#xff0c;可以通过远程控制和监测水表的运行情况&#xff0c;实现更加精准的水量计量和费用结算。那么&#xff0c;物联网阀控水表的计量准确度如何呢&#xff1f;下面我们将从以下几个方面进行详细…

sql中with as用法/with-as 性能调优/with用法

文章目录 一、概述二、基本语法三、使用场景3.1、定义CTE,并为每列重命名3.2、多次引用/多次定义3.3、with与union all联合使用3.4、with返回多种结果的值3.5、with与insert使用 四、递归查询4.1、语法4.2、使用场景4.2.1、用with递归构造1-10的数据4.2.2、with与insert递归造数…

flink to starrocks 问题集锦....

[问题排查]导入失败相关 - 问题排查 - StarRocks中文社区论坛 starrocks官网如下&#xff1a; Search StarRocks Docs starrocks内存配置项&#xff1a; 管理内存 Memory_management StarRocks Docs 问题1&#xff1a;实时写入starrocks &#xff0c;配置参数设置如下&a…

微信小程序,商城底部工具栏的实现

效果演示&#xff1a; 前提条件&#xff1a; 去阿里云矢量图标&#xff0c;下载8个图标&#xff0c;四个黑&#xff0c;四个红&#xff0c;如图&#xff1a; 新建文件夹icons&#xff0c;把图标放到该文件夹&#xff0c;然后把该文件夹移动到该项目的文件夹里面。如图所示 app…

第一次后端复习整理(JVM、Redis、反射)

1. JVM 文章仅为自身笔记 详情查看一篇文章掌握整个JVM&#xff0c;JVM超详细解析&#xff01;&#xff01;&#xff01; 1.1 什么是JVM jvm是Java虚拟机 1.2 Java文件的编译过程 程序员编写代码形成.java文件经过javac编译成.class文件再通过JVM的类加载器进入运行时数据…

论文分享:PowerTCP: Pushing the Performance Limits of Datacenter Networks

1 原论文的题目&#xff08;中英文&#xff09;、题目中包含了哪些关键词&#xff1f;这些关键词的相关知识分别是什么&#xff1f; 题目&#xff1a;PowerTCP: Pushing the Performance Limits of Datacenter Networks PowerTCP&#xff1a;逼近数据中心的网络性能极限 2 论…

app稳定性测试-iOS篇

稳定性测试&#xff1a;测试应用程序在长时间运行过程中是否存在内存泄漏、崩溃等问题&#xff0c;以确保应用程序具有较高的稳定性和可靠性。 对于安卓端&#xff0c;官方提供了很好的稳定性测试工具&#xff1a;monkey。 相比较而言&#xff0c;iOS则没有&#xff0c;而且当前…

013 怎么查看自己电脑的wifi密码

方法一&#xff1a;查看当前电脑连接的无线密码 步骤1&#xff1a; 打开windows命令行窗口&#xff0c;输入&#xff1a;ncpa.cpl 快速打开“控制面板”中的“网络连接”&#xff0c;如下图&#xff1a; 步骤2&#xff1a; 右键&#xff0c;打开“状态” 步骤3&#xff1a;…

【达哥讲网络】第3集:数据交换的垫基石——二层交换原理

专业的网络工程师在进行网络设计时&#xff0c;会事先规划好不同业务数据的转发路径&#xff0c;一方面是为了满足用户应用需求&#xff0c;另一方面是为了提高数据转发效率、充分利用各设备/各链路的硬件或带宽资源。在进行网络故障排除时&#xff0c;理顺各路数据的转发路径也…

uni-app优雅的实现时间戳转换日期格式

现在显示的格式如下图&#xff1a; 我期望统一格式&#xff0c;所以不妨前端处理一下&#xff0c;核心代码如下 filters: {// 时间戳处理formatDate: function(value, spe /) {value value * 1000let data new Date(value);let year data.getFullYear();let month data.…

交互式AI技术与模型部署:bert-base-chinese模型交互式问答界面设置

使用Gradio实现Question Answering交互式问答界面&#xff0c;首先你需要有一个已经训练好的Question Answering模型&#xff0c;这里你提到要使用bert-base-chinese模型。 Gradio支持PyTorch和TensorFlow模型&#xff0c;所以你需要将bert-base-chinese模型转换成PyTorch或Te…

为什么 Linux 内核协议栈会丢弃 SYN 数据包

最近了解到 SYN 数据包丢弃的问题&#xff0c;网上有一些资料&#xff0c;这里记录分享一下。 serverfault上的重要信息 tcp - No SYN-ACK Packet from server - Server Fault 信息如下&#xff1a; My embedded system with LwIP is the client and I have server1 and ser…

STM32MX配置EEPROM(AT24C02)------保姆级教程

———————————————————————————————————— ⏩ 大家好哇&#xff01;我是小光&#xff0c;嵌入式爱好者&#xff0c;一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子&#xff0c;使用STM32CUBEMX做了很多驱动&#x…

文件按关键字分组-切割-染色-写入excel

1. 背景 针对下面的文件data.csv&#xff0c;首先根据fid进行排序&#xff0c;然后分组&#xff0c;使相同fid的记录放到同一个excel文件中&#xff0c;并对每列重复的数据元素染上红色。 fid,user_id -1000078398032092029,230410010036537520 -1000078398032092029,23042301…