C#结合JavaScript实现多文件上传
目录
需求
引入
关键代码
操作界面
JavaScript包程序
服务端 ashx 程序
服务端上传后处理程序
小结
需求
在许多应用场景里,多文件上传是一项比较实用的功能。实际应用中,多文件上传可以考虑如下需求:
1、对上传文件的类型、大小有一个基本的控制。
2、上传文件时有一个进度显示,包括当前文件和整体进度。
3、上传后,在服务端后续事件进行一些处理。
引入
首先请在WEB应用程序根目录下创建COMMON目录,并引入 JavaScript 程序包,该程序包已经打包,下载地址为:https://download.csdn.net/download/michaelline/88615565。
下载成功后解压到COMMON目录即可,请引入如下图中的 JS 文件:

另外,我们还需要在 app_data目录下创建 ajaxUploadFiles 子目录,以备上传创建文件使用。
关键代码
操作界面
界面上放置标准的 input file 控件,并将其服务器化,即 runat="server"。点击选择文件,选中所有目标文件后,自动实现文件上传功能。
示例界面如下:
示例UI代码如下:
<input class="file" type="file" id="ajaxMfile" runat="server" onbeginupload="ajax_uploadFiles_beginUpload" onprogressupload="ajax_uploadFiles_progressUpload" onendupload="ajax_uploadFiles_endUpload" multiple="multiple" allowtype="pptx|docx|mp3|txt|std" allowsize="500m|100m" fileindex="0" name="fileupload"serverbuttonid="ajaxEndBtn" serverfilelistid="ajaxReturnFileName"progresspanelid="ajaxMfileProgressPanel"onchange="ajax_uploadFiles(this);return false" /><asp:TextBox runat="server" Width="100%" ID="ajaxReturnFileName" style="display:none" ></asp:TextBox><br /><asp:button ID="ajaxEndBtn" text="后台处理" runat="server" style="display:none" onclick="ajaxEndBtn_Click" /><br /><br /><table style="display:none; color:White" id="ajaxMfileProgressPanel"><tr><td >当前文件:</td><td style="position:relative; padding:0px"><asp:Label Font-Size="9pt" style="z-index:1;position:absolute;left:0px;top:-9px;" Width="300px" runat="server" ID="ajax_uploadFiles_curfilename"/></td></tr><tr><td style="position:relative; padding:0px;width:120px">当前文件进度<asp:Label style="z-index:1;position:absolute;left:85px;top:-9px;" runat="server" Font-Size="9pt" ID="ajax_uploadFiles_upprogress"></asp:Label></td><td style="position:relative; padding:10px"><img id="ajax_uploadFiles_curprogress" style="z-index:1;position:absolute;left:0px;top:4px;width:0px;height:12px" alt="" src="/common/Jquery/images/win7progress.jpg" /><div id="ajax_uploadFiles_curbg" style="z-index:0;position:absolute;left:0px;top:4px;width:300px;height:12px;background-color:Gray"></div></td></tr><tr><td style="position:relative; padding:0px">上传总量进度<asp:Label style="z-index:1;position:absolute;left:85px;top:-9px;" runat="server" Font-Size="9pt" ID="ajax_uploadFiles_cprogress"></asp:Label></td><td style="position:relative; padding:10px"><img id="ajax_uploadFiles_totalprogress" style="z-index:1;position:absolute;left:0px;top:4px;width:0px;height:12px" alt="" src="/common/Jquery/images/win7progress2.jpg" /><div id="ajax_uploadFiles_totalbg" style="z-index:0; position:absolute;left:0px;top:4px;width:300px;height:12px;background-color:Gray"></div></td></tr></table><table style="color:White; width:100%"><tr><td style="position:relative"><asp:Label runat="server" Font-Size="11pt" ID="ajax_uploadFiles_serverProcessTip"></asp:Label></td></tr></table>
input file 控件的一些设置如下:
(1)onbeginupload="ajax_uploadFiles_beginUpload" js方法,开始上传前事件,默认值
(2)onprogressupload="ajax_uploadFiles_progressUpload" js方法,上传中事件,默认值
(3)onendupload="ajax_uploadFiles_endUpload" js方法,选择完文件上传事件,默认值
(4)multiple="multiple" 控件属性,允许多文件选中上传
(5)allowtype="pptx|docx|mp3|txt|std" 自定义属性,允许上传的文件类型,以 | 分隔
(6)allowsize="500m|100m" 自定义属性,允许上传的文件最大尺寸,可以以 | 分隔,并一一对应,如果不对应,则根据 allowtype 的设置从左至右进行匹配
如举例中的设置则表示为,pptx 允许最大 500M , docx 最大 100M,后面未设置则均为100M
(7) serverbuttonid="ajaxEndBtn" 自定义属性,执行的服务器按钮ID,默认值
(8)serverfilelistid="ajaxReturnFileName" 自定义属性,服务器端返回的文件ID列表,默认值
(9)οnchange="ajax_uploadFiles(this);return false" 自定义属性,js方法,选择文件后自动执行上传功能,默认值
根据示例代码的设置,以上部分除了 allowtype和 allowsize 均可以不用改变设置。
上传中的效果如下图:

JavaScript包程序
本包程序实现了前面设置的界面元素方法、事件、属性的实现及对文件上传的客户端控制,示例代码如下:
//批量上传文件的内置默认辅助方法,表示每上传一个文件之前发生的事件,//事件的fileObj参数代表 file对象(上传控件),由主方法自动传入,开发者可以重新指定自定义方法function ajax_uploadFiles_beginUpload(fileObj) {var fIndex = parseInt(fileObj.getAttribute("fileindex"), 10);if (fIndex == 0) {document.getElementById('ajax_uploadFiles_serverProcessTip').innerHTML = '';document.getElementById("ajax_uploadFiles_upprogress").innerHTML = "";document.getElementById("ajax_uploadFiles_cprogress").innerHTML = "";document.getElementById("ajax_uploadFiles_totalprogress").style.width = "0px";document.getElementById(fileObj.getAttribute("serverfilelistid")).value = "";}document.getElementById("ajax_uploadFiles_curfilename").innerHTML = fileObj.files[fIndex].name;}//批量上传文件的内置默认辅助方法,表示当前正在上传文件时发生的事件(主要用于显示上传进度),//事件的fileObj参数代表 file对象(上传控件), loaded:已经上传的文件总字节, total:正在上传的文件总字数,// percent:不超过100的整数,表示为百分比。这些参数由主方法自动传入,开发者可以重新指定自定义方法function ajax_uploadFiles_progressUpload(fileObj, loaded, total, percent) {document.getElementById("ajax_uploadFiles_upprogress").innerHTML = ("" + percent + "%");var curb = parseInt(document.getElementById("ajax_uploadFiles_curbg").style.width, 10);document.getElementById("ajax_uploadFiles_curprogress").style.width = Math.floor(curb * loaded / total) + "px";}//批量上传文件的内置默认辅助方法,表示当前文件上传完成时发生的事件(主要用于处理文件上传后的跟踪处理,并且返回服务器上保存的文件列到一个文本框中,以|分隔),//事件的fileObj参数代表 file对象(上传控件), type:上传状态返回,包括success成功,error失败, //data:文件的数据,暂时未使用, desfile:要保存在服务器上的文件名// 这些参数由主方法自动传入,开发者可以重新指定自定义方法function ajax_uploadFiles_endUpload(fileObj, type, data, desfile) {var fIndex = parseInt(fileObj.getAttribute("fileindex"), 10);var filecount = fileObj.files.length;document.getElementById(fileObj.getAttribute("serverfilelistid")).value += desfile + "|";var totalb = parseInt(document.getElementById("ajax_uploadFiles_totalbg").style.width, 10);document.getElementById("ajax_uploadFiles_totalprogress").style.width = Math.floor(totalb * (fIndex + 1) / filecount) + "px";document.getElementById("ajax_uploadFiles_cprogress").innerHTML = ("" + Math.floor(100 * (fIndex + 1) / filecount) + "%");if (fIndex < filecount - 1) {fIndex++;fileObj.setAttribute("fileindex", fIndex);ajax_uploadFiles(fileObj);return;}fileObj.setAttribute("fileindex", 0);if (type == "success") {document.getElementById('ajaxMfile').style.display='none';document.getElementById('ajax_uploadFiles_serverProcessTip').innerHTML = '上传完成!正在进行后台处理...';document.getElementById(fileObj.getAttribute("serverbuttonid")).click();} else if (type == "error") {alert("error");}}//生成一个guidfunction newguid() {function S4() {return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);}return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());}//批量上传文件的主方法,fileObj参数代表 file对象(上传控件)function ajax_uploadFiles(fileObj) {var formData = new FormData();var fIndex = parseInt(fileObj.getAttribute("fileindex"), 10);var filecount = fileObj.files.length;if (filecount == 0) {alert('请先浏览选择文件...');return;}var uploadSessionId = newguid();var upfile = fileObj.files[fIndex].name;var dotpos = upfile.lastIndexOf('.');var desfile = "";var exname = "";if (dotpos > 0) {exname = upfile.substring(dotpos + 1, upfile.length);desfile = uploadSessionId + upfile.substring(0, dotpos) + '.' + exname;} else {desfile = uploadSessionId + upfile;}// alert(Math.round(upsize / 1024));if (fIndex == 0) {var allowtype = fileObj.getAttribute("allowtype");var allowsize = fileObj.getAttribute("allowsize");var at = allowtype.split('|');var as = allowsize.split('|');for (var j = 0; j < filecount; j++) {var validfile = fileObj.files[j].name;var upsize = fileObj.files[j].size;var validdotpos = validfile.lastIndexOf('.');var validexname = "";if (validdotpos > 0) {validexname = validfile.substring(validdotpos + 1, validfile.length);}var i = 0;if (allowtype != "") {var find = false;for (i = 0; i < at.length; i++) {if (at[i].toLowerCase() == validexname.toLowerCase()) {find = true;break;}}if (find == false) {alert("文件" + validfile + "上传的类型不符合要求!仅允许上传扩展名为:" + allowtype.split("|").join("、") + "的文件。");fileObj.style.display = '';document.getElementById(fileObj.getAttribute("progresspanelid")).style.display = 'none';var t = fileObj;t.outerHTML = t.outerHTML;return;}}if (allowsize != "") {if (at.length <= as.length) {} else {i = 0;}as[i] = as[i].toLowerCase();var csize = parseInt(as[i]);var tsize = upsize;if (as[i].lastIndexOf('k') != -1) {csize = csize * 1024;tsize = Math.round(upsize / 1024) + "KB";} else if (as[i].lastIndexOf('m') != -1) {csize = csize * 1024 * 1024;tsize = Math.round(upsize / 1024 / 1024) + "MB";} else if (as[i].lastIndexOf('g') != -1) {csize = csize * 1024 * 1024 * 1024;tsize = Math.round(upsize / 1024 / 1024 / 1024) + "GB";} else if (as[i].lastIndexOf('t') != -1) {csize = csize * 1024 * 1024 * 1024 * 1024;tsize = Math.round(upsize / 1024 / 1024 / 1024 / 1024) + "TB";}if (upsize > csize) {alert("上传文件" + validfile + "的大小近" + tsize + ",系统规定大小不能超过" + as[i].toUpperCase() + ",请重新选择。");fileObj.style.display = '';document.getElementById(fileObj.getAttribute("progresspanelid")).style.display = 'none';var t = fileObj;t.outerHTML = t.outerHTML;return;}}} //j} // findex// document.getElementById(callObjId).disabled = 'disabled';// if (beginFuncName != null) {// beginFuncName(fIndex, filecount,upfile);// }fileObj.style.display = 'none';document.getElementById(fileObj.getAttribute("progresspanelid")).style.display = '';var findfunc = fileObj.getAttribute("onbeginupload");if (eval(findfunc)) {var execfunc = eval(findfunc);// alert(findfunc);execfunc(fileObj);}formData.append("file", fileObj.files[fIndex]); //append()里面的第一个参数file对应permission/upload里面的参数filevar processUploadUrl = window.location.protocol + "//" + window.location.host + "//common//uploadfile.ashx?guid=" + uploadSessionId;$.ajax({type: "post",async: true, //这里要设置异步上传,才能成功调用myXhr.upload.addEventListener('progress',function(e){}),progress的回掉函数Accept: 'text/html;charset=UTF-8',data: formData,contentType: "multipart/form-data",url: processUploadUrl,processData: false, // 告诉jQuery不要去处理发送的数据contentType: false, // 告诉jQuery不要去设置Content-Type请求头xhr: function () {myXhr = $.ajaxSettings.xhr();if (myXhr.upload) { // check if upload property existsmyXhr.upload.addEventListener('progress', function (e) {var loaded = e.loaded; //已经上传大小情况 var total = e.total; //附件总大小 var percent = Math.floor(100 * loaded / total); //已经上传的百分比 // if (progressFuncName != null) {// progressFuncName(loaded, total, percent);// }var findfunc = fileObj.getAttribute("onprogressupload");if (eval(findfunc)) {var execfunc = eval(findfunc);// alert(findfunc);execfunc(fileObj, loaded, total, percent);}// $("#processBar").css("width", percent);}, false); // for handling the progress of the upload}return myXhr;},success: function (data) {if (fIndex == fileObj.files.length - 1) {fileObj.style.display = '';document.getElementById(fileObj.getAttribute("progresspanelid")).style.display = 'none';var t = fileObj;t.outerHTML = t.outerHTML;}// if (endFuncName != null) {// endFuncName("success", data, desfile, fIndex,filecount);// }var findfunc = fileObj.getAttribute("onendupload");if (eval(findfunc)) {var execfunc = eval(findfunc);// alert(findfunc);execfunc(fileObj, "success", data, desfile);}},error: function (XMLHttpRequest, textStatus, errorThrown) {alert(errorThrown);if (endFuncName != null) {endFuncName(fileObj, "error", null, '');}}});}
服务端 ashx 程序
ashx,一般处理程序(HttpHandler)是·NET众多web组件的一种。一个 httpHandler 接受并处理一个http请求,类似 Java 中的 servlet 。
本程序实现服务器端上传文件的接收和另存操作,在这里我们存为uploadfile.ashx,代码如下:
<%@ WebHandler Language="C#" Class="Handler" %>using System;
using System.Web;
using System.IO;public class Handler : IHttpHandler {public void ProcessRequest (HttpContext context) {if (context.Request.Files.Count > 0){//HttpContext.Current.Request.FilePath;string strPath = System.Web.HttpContext.Current.Server.MapPath("~/app_data/ajaxUploadFiles/");string strName = context.Request.Files[0].FileName;string ext=Path.GetExtension(strName);string filename =HttpContext.Current.Request.QueryString["guid"].ToString()+Path.GetFileNameWithoutExtension(strName);if(ext!=""){filename = filename + ext;}context.Request.Files[0].SaveAs(System.IO.Path.Combine(strPath, filename));}}public bool IsReusable {get {return false;}}}
服务端上传后处理程序
在多个文件上传到服务器后,我们需要对文件进行后期处理,在前端我们设置了ID为 “ajaxEndBtn”的服务器按钮,进行模拟调用其 click 事件。
服务器端按钮处理事件示例代码如下:
void ajaxEndBtn_Click(object sender, EventArgs e){//得到保存后的文件名列表string[] upfiles = ajaxReturnFileName.Text.Split('|');//给予用户基本的提示ajax_uploadFiles_serverProcessTip.Text = "本次上传分析:共计上传" + (upfiles.Length - 1).ToString() + "个文件。";//遍历上传文件列表,进行后期处理foreach (string filename in upfiles){if (filename.Trim() == "") continue;string upfilename = Request.PhysicalApplicationPath + "app_data\\ajaxUploadFiles\\" + filename;string exname = System.IO.Path.GetExtension(upfilename);//执行业务处理程序}
小结
以上提供的代码仅供参考,默认的设置仅可能提供最基础的实现,比如 ashx 程序还需要进行安全控制;进度图片和UI可以重新设计;实际的业务可以根据需求对控件的属性、事件进行重写。
以上就是自己的一些分享,时间仓促,不妥之处还请大家批评指正!
相关文章:
C#结合JavaScript实现多文件上传
目录 需求 引入 关键代码 操作界面 JavaScript包程序 服务端 ashx 程序 服务端上传后处理程序 小结 需求 在许多应用场景里,多文件上传是一项比较实用的功能。实际应用中,多文件上传可以考虑如下需求: 1、对上传文件的类型、大小…...
STM32——继电器
继电器工作原理 单片机供电 VCC GND 接单片机, VCC 需要接 3.3V , 5V 不行! 最大负载电路交流 250V/10A ,直流 30V/10A 引脚 IN 接收到 低电平 时,开关闭合。...
性能监控体系:InfluxDB Grafana Prometheus
InfluxDB 简介 什么是 InfluxDB ? InfluxDB 是一个由 InfluxData 开发的,开源的时序型数据库。它由 Go 语言写成,着力于高性能地查询与存储时序型数据。 InfluxDB 被广泛应用于存储系统的监控数据、IoT 行业的实时数据等场景。 可配合 Te…...
CS106L2023 and CS106B 环境配置(详细教程)
1.问题: (1)CS106L 运行./setup.sh 脚本时出错 (windows 请下载git,在git bash 打开运行) (2)CS106B,QT构建 构建错误:一般构建错误,例如 Erro…...
Docker-多容器应用
一、概述 到目前为止,你一直在使用单个容器应用。但是,现在您将 MySQL 添加到 应用程序堆栈。经常会出现以下问题 - “MySQL将在哪里运行?将其安装在同一个 容器还是单独运行?一般来说,每个容器都应该做一件事&#x…...
Golang导入导出Excel表格
最近项目开发中有涉及到Excel的导入与导出功能,特别是导出表格时需要特定的格式(单元格合并等),废话不多说,直接上代码了。 首先用到一个第三方库,实测还是很强大很好用的,就是这个https://git…...
基于Maven的Spring Boot应用版本号获取解析
引言 在Spring Boot应用的开发和部署中,了解应用的版本号对于管理和监控应用至关重要。本文将深入解析一种基于Maven打包的Spring Boot应用中,根据不同的运行环境获取应用版本号的解决方案。在开始介绍代码之前,我们先来了解一下可能的文件目…...
LLM微调(二)| 微调LLAMA-2和其他开源LLM的两种简单方法
本文将介绍两种开源工具来微调LLAMA-2。 一、使用autotrain-advanced微调LLAMA-2 AutoTrain是一种无代码工具,用于为自然语言处理(NLP)任务、计算机视觉(CV)任务、语音任务甚至表格任务训练最先进的模型。 1…...
AVP对纵向控制ESP(Ibooster)的需求规范
目录 1. 版本记录... 3 2. 文档范围和控制... 4 2.1 目的/范围... 4 2.2 文档冲突... 4 2.3 文档授权... 4 2.4 文档更改控制... 4 3. 功能概述... 5 4. 系统架构... 6 5. 主要安全目标... 7 5.1 …...
小模型学习(1)-人脸识别
【写作背景】因为最近一直在研究大模型,在与客户进行交流时,如果要将大模型的变革性能力讲清楚,就一定要能将AI小模型的一些原理和效果讲清楚,进而形成对比。当然这不是一件简单的事情,一方面大模型分析问题的的本质原…...
sublime Text使用
1、增加install 命令面板 工具(tool)->控制面板(command palette) -> 输入install ->安装第一个install package controller,以下安装过了,所以没展示 2、安装json格式化工具 点击install package,等几秒会进入控制面板࿰…...
基于深度学习的yolov7植物病虫害识别及防治系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介简介YOLOv7 系统特性工作流程 二、功能三、系统四. 总结 一项目简介 # YOLOv7植物病虫害识别及防治系统介绍 简介 该系统基于深度学习技术,采…...
Leetcode 2963. Count the Number of Good Partitions
Leetcode 2963. Count the Number of Good Partitions 1. 解题思路2. 代码实现 题目链接:2963. Count the Number of Good Partitions 1. 解题思路 这一题根据题意,显然我们可以将其先分为 n n n个原子partition,确保任意两个partition之间…...
C语言动态内存经典笔试题分析
C语言动态内存经典笔试题分析 文章目录 C语言动态内存经典笔试题分析1. 题目一2. 题目二3. 题目三4. 题目四 1. 题目一 void GetMemory(char *p){p (char *)malloc(100);} void Test(void){char *str NULL;GetMemory(str);strcpy(str, "hello world");printf(str)…...
截断正态分布stats.truncnorm()X.rvs(10000)
就是在均值和方差之外,再指定正态分布随机数群的上下限,如 [ μ − 3 σ , μ 3 σ ] [\mu-3\sigma,\mu3\sigma] [μ−3σ,μ3σ] stats.truncnorm()参数 X stats.truncnorm(-2, 2, locmu, scalesigma) -2 2是截断的正态分布…...
第59天:django学习(八)
事务 事务是MySQL数据库中得一个重要概念,事务的目的:为了保证多个SQL语句执行成功,执行失败,前后保持一致,保证数据安全。 开启事务的三个关键字 start transaction commit rollback 开启事务 from django.db import transaction…...
举例说明自然语言处理(NLP)技术。
本文章由AI生成! 以下是自然语言处理(NLP)技术的一些例子: 机器翻译:将一种语言翻译成另一种语言的自动化过程。常见的机器翻译系统包括谷歌翻译,百度翻译等。 语音识别:将口头语言转换成文本…...
echarts地图marker自定义图标并添加点击事件
symbol如果引用https图片链接会报403,直接引用本地 series: [{type: scatter, // 使用散点图系列 coordinateSystem: geo, // 设置坐标系为地理坐标系 zlevel: 100,data: [{name: 上海,value: [121.48, 31.22], // 上海的经纬度坐标 symbol: image:// require(/…...
C盘瘦身,C盘清理
以下只是我的C盘清理经验~ 一.【用软件简单清理C盘】 使用一些垃圾清理软件,简单的初步把C盘先清理一遍。(这种软件太多我就不推荐了……) 二.【WPS清理大师】 因为我电脑装了WPS,发现右键单击C盘有个选项【释放C盘空间】…...
STM32F103
提示:来源正点原子,参考STM32F103 战舰开发指南V1.3PDF资料 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 开发环境硬件普中科技,接…...
TDA4VEN-Q1入门级ADAS SoC:异构架构与全景泊车方案实战
1. 项目概述:为什么选择TDA4VEN-Q1这颗“入门级”SoC?在汽车电子,尤其是ADAS(高级驾驶辅助系统)领域,选型永远是项目成败的第一步。面对市场上琳琅满目的处理器,从动辄几十TOPS算力的域控制器芯…...
终极免费方案:5分钟破解Cursor AI试用限制,永久享受Pro功能
终极免费方案:5分钟破解Cursor AI试用限制,永久享受Pro功能 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve …...
终极指南:如何快速构建中文手写识别AI系统(免费数据集)
终极指南:如何快速构建中文手写识别AI系统(免费数据集) 【免费下载链接】Traditional-Chinese-Handwriting-Dataset Open source traditional chinese handwriting dataset. 项目地址: https://gitcode.com/gh_mirrors/tr/Traditional-Chin…...
ECB02蓝牙主机模式避坑实录:STM32F103C8T6连接失败、绑定不清除的5个常见问题解决
ECB02蓝牙主机模式实战避坑指南:STM32F103C8T6连接异常全解析 当你第一次尝试用STM32F103C8T6通过ECB02蓝牙模块建立主机连接时,大概率会遇到各种"灵异现象":模块毫无反应、AT指令石沉大海、设备死活连不上旧设备、数据乱码像天书……...
浏览器中优雅查看Markdown文件的终极解决方案:Markdown Viewer完全指南
浏览器中优雅查看Markdown文件的终极解决方案:Markdown Viewer完全指南 【免费下载链接】markdown-viewer Markdown Viewer / Browser Extension 项目地址: https://gitcode.com/gh_mirrors/ma/markdown-viewer 你是否经常需要查看GitHub上的README文件、技术…...
对比直接使用厂商 API 观察通过 Taotoken 进行成本管理的便利性
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比直接使用厂商 API 观察通过 Taotoken 进行成本管理的便利性 对于需要同时调用多个大语言模型的个人开发者或小项目而言&#x…...
G-Helper:华硕笔记本性能控制的终极轻量级替代方案
G-Helper:华硕笔记本性能控制的终极轻量级替代方案 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Exper…...
2026年最新实测15款降AIGC平台红黑榜!
2026 年的毕业季注定不平凡。教育部最新发布的《学术诚信管理规范》明确指出,本科毕业论文 AIGC 率不得超过 35%,而重点高校如清华、北大等已将标准压至 25% 以内,硕士及以上学位论文更是严格控制在 18% 以下。与此同时,各大检测平…...
AutoLegalityMod:如何在15分钟内创建完全合法的宝可梦数据
AutoLegalityMod:如何在15分钟内创建完全合法的宝可梦数据 【免费下载链接】PKHeX-Plugins Plugins for PKHeX 项目地址: https://gitcode.com/gh_mirrors/pk/PKHeX-Plugins 从数据混乱到精准合规的技术实现 每个宝可梦训练师都曾面临这样的困境:…...
电脑自动化 OpenClaw 安装教程 自然语言操控电脑
告别命令行!Windows OpenClaw 一键安装,5 分钟一键部署 ✨ 前言 OpenClaw(小龙虾)是一款能直接操控电脑的 AI 智能体,无需复杂配置、不用敲命令行,Windows 环境下全程可视化操作,5 分钟即可完…...
