解决AJAX中FormData与额外数据传递难题

解决ajax中formdata与额外数据传递难题

本文旨在解决在使用jQuery AJAX结合FormData进行文件上传时,如何正确地传递额外变量(如ID)到服务器端的问题。我们将深入探讨常见错误及其原因,并提供一个安全高效的解决方案,即通过FormData.append()方法将所有数据统一封装,确保服务器能够正确接收。此外,文章还将强调并提供关键的SQL注入防护建议,以保障数据操作的安全性。

理解FormData与AJAX数据传输

在使用AJAX进行文件上传时,FormData对象是处理multipart/form-data编码请求的关键。它允许我们将文件和普通表单字段组合成一个可发送的数据包。当使用jQuery的$.ajax()方法发送FormData时,通常需要设置以下两个重要的参数:

contentType: false:指示jQuery不要设置Content-Type头部。FormData对象会自行设置正确的multipart/form-data头部,包括边界字符串。processData: false:指示jQuery不要将data选项中的数据转换为查询字符串。这对于FormData对象至关重要,因为我们希望直接发送FormData对象本身。

错误的数据传递方式及其原因

许多开发者在尝试将额外变量(例如一个ID)与FormData对象一起发送时,可能会尝试以下方式:

var id = ""; var form_data = new FormData();// ... 添加文件到form_data ...$.ajax({    url:"upload.php",    data: {id : id, form_data}, // 错误示例    method:"POST",    contentType: false,    cache: false,    processData: false,    // ... 其他设置 ...});

这种做法是错误的,原因如下:

processData: false的冲突:当processData设置为false时,jQuery会预期data选项是一个可以直接发送的原始数据(如FormData对象或字符串)。然而,{id : id, form_data}是一个普通的JavaScript对象。对象序列化问题:即使processData为true,jQuery尝试序列化{id : id, form_data}时,它会遇到form_data这个FormData对象。JavaScript在尝试将一个对象转换为字符串时,通常会调用其toString()方法,对于FormData对象,这会导致其被序列化为[object Object]。因此,服务器端将无法正确解析form_data中的文件和数据。PHP无法识别:由于上述序列化问题,服务器端的PHP脚本将无法通过$_POST或$_FILES数组获取到form_data中包含的任何数据。

正确的FormData与额外数据组合传递方法

正确的做法是将所有需要发送的数据,无论是文件还是普通字段,都通过FormData.append()方法添加到同一个FormData对象中。这样,整个FormData对象就可以作为一个统一的实体发送到服务器。

客户端代码示例 (JavaScript/jQuery)

<?php    // 确保id变量已设置,并进行安全检查    $id = isset($_GET['lcid']) && $_GET['lcid'] !== NULL ? $_GET['lcid'] : null;    if ($id === null) {        echo "window.location = 'insurt-documents.php';";        exit(); // 终止脚本执行    }?>$(document).ready(function(){    // 假设您已经有了文件选择逻辑和错误处理    // ... 检查文件数量等逻辑 ...    var error_images = '';    var form_data = new FormData();    var files = $('#multiple_files')[0].files;    if(files.length > 15) {        error_images += '您不能选择超过15个文件';        // 显示错误信息并阻止上传        $('#error_multiple_files').html('
'); return; } else { // 将所有选定的文件添加到FormData对象 for(var i = 0; i < files.length; i++) { form_data.append('multiple_files[]', files[i]); // 使用数组命名以便服务器端接收多个文件 } } // 将额外变量 'id' 添加到 FormData 对象 // 注意:这里的$id是PHP变量,在页面加载时会被替换为实际值 var postId = ""; form_data.append("id", postId); $.ajax({ url:"upload.php", data: form_data, // 直接传递FormData对象 method:"POST", contentType: false, // 不设置Content-Type头部 cache: false, processData: false, // 不处理数据 beforeSend:function(){ $('#error_multiple_files').html('
'); }, success:function(data) { $('#error_multiple_files').html('
'); // 假设load_image_data()函数用于刷新图片列表 load_image_data(); // 可选:处理服务器返回的数据 'data' console.log(data); }, error: function(jqXHR, textStatus, errorThrown) { $('#error_multiple_files').html('
'); console.error("AJAX Error: ", textStatus, errorThrown); } });});

服务器端数据获取 (PHP)

在upload.php文件中,你可以像处理普通表单提交一样,通过$_POST数组获取额外变量,通过$_FILES数组获取上传的文件。

connect_error) {    die("数据库连接失败: " . $conn->connect_error);}// 获取通过FormData.append("id", ...) 传递的ID// 注意:即使是FormData,普通字段也会在$_POST中$postId = isset($_POST['id']) ? $_POST['id'] : null;if ($postId === null) {    echo "错误:未接收到文章ID。";    exit();}// 获取上传的文件// 如果客户端使用了 'multiple_files[]' 命名,$_FILES['multiple_files'] 将是一个数组if (isset($_FILES['multiple_files']) && is_array($_FILES['multiple_files']['name'])) {    $fileNames = $_FILES['multiple_files']['name'];    $fileTmps = $_FILES['multiple_files']['tmp_name'];    $fileErrors = $_FILES['multiple_files']['error'];    foreach ($fileNames as $index => $fileName) {        if ($fileErrors[$index] === UPLOAD_ERR_OK) {            $tmpPath = $fileTmps[$index];            $newFileName = uniqid() . '_' . basename($fileName); // 生成唯一文件名            $uploadDir = 'uploads/'; // 您的上传目录            if (!is_dir($uploadDir)) {                mkdir($uploadDir, 0777, true); // 如果目录不存在则创建            }            $targetPath = $uploadDir . $newFileName;            if (move_uploaded_file($tmpPath, $targetPath)) {                // 文件移动成功,现在可以插入数据库                // !!! 重要:这里需要使用预处理语句防止SQL注入 !!!                $query = "INSERT INTO tbl_image (postid, image_name, image_description) VALUES (?, ?, ?)";                // 使用预处理语句                $stmt = $conn->prepare($query);                if ($stmt === false) {                    echo "SQL准备失败: " . $conn->error;                    continue; // 跳过当前文件                }                // 绑定参数                $description = ''; // 假设描述为空或从其他字段获取                $stmt->bind_param("iss", $postId, $newFileName, $description); // i: integer, s: string                // 执行语句                if ($stmt->execute()) {                    // echo "文件 '" . htmlspecialchars($fileName) . "' 上传成功并记录到数据库。
"; } else { echo "文件 '" . htmlspecialchars($fileName) . "' 数据库插入失败: " . $stmt->error . "
"; } $stmt->close(); } else { echo "文件 '" . htmlspecialchars($fileName) . "' 移动失败。
"; } } else { echo "文件 '" . htmlspecialchars($fileName) . "' 上传错误,错误码: " . $fileErrors[$index] . "
"; } } echo "所有文件处理完毕。";} else { echo "未检测到上传文件或上传文件错误。";}$conn->close();?>

重要安全警告:SQL注入防护

原始的PHP代码中存在严重的SQL注入漏洞:

$query = "INSERT INTO tbl_image (postid, image_name, image_description)           VALUES ('".$id."', '".$file_name."', '')";

直接将用户输入($id和$file_name)拼接到SQL查询字符串中是非常危险的。恶意用户可以通过在输入中插入SQL代码来操纵您的数据库,例如删除数据、窃取信息甚至完全控制数据库。

防护措施:使用预处理语句和参数化查询

防止SQL注入最有效的方法是使用预处理语句(Prepared Statements)和参数化查询。这是一种将SQL命令与数据分离的技术,数据库服务器会在执行查询前对命令进行解析,并确保数据不会被解释为SQL命令的一部分。

以下是使用PHP mysqli 扩展实现预处理语句的示例:

// 假设 $conn 是您的mysqli数据库连接对象// $postId 和 $newFileName 是您从 $_POST 和 $_FILES 获取的数据// 1. 准备SQL语句,使用占位符 (?)$query = "INSERT INTO tbl_image (postid, image_name, image_description) VALUES (?, ?, ?)";$stmt = $conn->prepare($query);// 检查语句是否准备成功if ($stmt === false) {    die("SQL准备失败: " . $conn->error);}// 2. 绑定参数// 第一个参数是类型字符串,表示后续参数的类型:// 'i' 代表 integer (整数)// 'd' 代表 double (浮点数)// 's' 代表 string (字符串)// 'b' 代表 blob (二进制数据)$description = ''; // 假设描述为空或从其他字段获取$stmt->bind_param("iss", $postId, $newFileName, $description); // 3. 执行语句if ($stmt->execute()) {    echo "数据插入成功。";} else {    echo "数据插入失败: " . $stmt->error;}// 4. 关闭语句$stmt->close();// $conn->close(); // 在所有操作完成后关闭连接

为什么预处理语句有效?

分离命令与数据:数据库在收到预处理语句时,会先编译SQL命令结构,然后将数据作为独立的值传递给占位符。这意味着任何用户输入的数据都只能作为数据,而不能改变SQL命令的结构。性能提升:对于重复执行的查询,数据库可以缓存预处理语句的执行计划,从而提高性能。

重要参考资源:

Bobby Tables – 关于SQL注入的简单解释PHP Delusions – MySQLi 教程PHP手册 – MySQLi 预处理语句Stack Overflow – 如何在PHP中防止SQL注入?

总结与最佳实践

在AJAX中使用FormData上传文件并传递额外数据时,核心原则是将所有数据统一添加到FormData对象中,而不是尝试将其嵌套在另一个JavaScript对象中。这通过form_data.append(‘key’, value)方法实现,并配合contentType: false和processData: false的AJAX设置。

同时,任何涉及用户输入与数据库交互的操作,都必须严格遵循安全实践,尤其是使用预处理语句和参数化查询来彻底防范SQL注入攻击。这不仅能保护您的数据安全,也能避免因意外的输入值导致的语法错误。始终将数据安全放在首位,是任何专业开发不可或缺的一部分。

以上就是解决AJAX中FormData与额外数据传递难题的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1294613.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
使用 AJAX 上传文件时传递额外数据的方法
上一篇 2025年12月11日 10:23:12
下一篇 2025年12月11日 10:23:27

相关推荐

  • 可能是目前效果最好的开源生图模型,混元生图 3.0 来了

    可能是目前效果最好的开源生图模型,混元生图 3.0 来了可能是目前效果最好的开源生图模型,混元生图 3.0 来了可能是目前效果最好的开源生图模型,混元生图 3.0 来了可能是目前效果最好的开源生图模型,混元生图 3.0 来了

    腾讯混元最新发布并开源原生多模态生图模型——混元图像 3.0(hunyuanimage 3.0)! 模型参数规模高达 80B,是目前参数量最大的开源生图模型。 同时,HunyuanImage 3.0 将理解与生成一体化融合,也是首个开源工业级原生多模态生图模型,效果对标业界头部闭源模型,堪称目前开源…

    2026年9月26日 • 用户投稿
    400
  • 如何用Java制作个人任务提醒应用

    使用Java创建任务提醒应用,核心功能包括任务管理与定时提醒。2. 设计Task类封装标题、描述、截止时间与完成状态,用LocalDateTime处理时间。3. 任务存储于List中,通过ObjectOutputStream序列化实现持久化。4. 利用ScheduledExecutorService…

    2026年9月26日
    100
  • 一键PHP环境可以同时跑多个PHP版本吗_多版本共存实现

    多PHP版本共存可行。通过宝塔、phpStudy等集成环境或手动配置Nginx+多PHP-FPM,可实现不同站点使用不同PHP版本,需注意扩展兼容性、端口冲突及安全维护。 一键PHP环境通常指的是集成化的开发环境工具,比如 XAMPP、WAMP、宝塔面板 或 phpStudy 这类软件。这类工具默认…

    2026年9月26日
    000
  • Google浏览器官网入口一键直达

    Google浏览器官网入口一键直达Google浏览器官网入口一键直达Google浏览器官网入口一键直达Google浏览器官网入口一键直达

    Google浏览器官网入口一键直达地址是https://www.google.cn/chrome/,该网址提供简洁界面、多标签管理、智能搜索、网页翻译等功能,并支持跨设备同步书签、历史记录和密码,具备高效性能与安全更新。 Google浏览器官网入口一键直达在哪里?这是不少网友都关注的,接下来由PHP…

    2026年9月26日 • 用户投稿
    000
  • Win7系统如何让壁纸变换淡入淡出

    Win7系统如何让壁纸变换淡入淡出Win7系统如何让壁纸变换淡入淡出Win7系统如何让壁纸变换淡入淡出Win7系统如何让壁纸变换淡入淡出

    在windows 7操作系统里,除了常规方式更换桌面背景之外,还有一种更为高级的切换模式——即淡入淡出效果。接下来,win10系统之家的小编将为您详细讲解具体的操作步骤。 首先,准备好您想要用于淡入淡出效果的桌面背景图片,并调整更换时间间隔为10秒(当然,您可以依据需要自行调整此参数),如下图所示:…

    2026年9月26日 • 用户投稿
    000
  • AI辩论教练:用豆包AI+Character模拟对手训练逻辑反应

    AI辩论教练:用豆包AI+Character模拟对手训练逻辑反应AI辩论教练:用豆包AI+Character模拟对手训练逻辑反应AI辩论教练:用豆包AI+Character模拟对手训练逻辑反应AI辩论教练:用豆包AI+Character模拟对手训练逻辑反应

    你可以使用豆包ai和character.ai进行辩论训练,具体步骤包括:1.选择合适的平台,豆包ai适合快速访问,character.ai适合丰富角色设定;2.创建或选择辩论角色并设定背景、立场和风格;3.明确辩题并输入给ai;4.轮流发言并及时记录分析;5.利用豆包ai进行观点碰撞、论据挖掘和模拟…

    2026年9月26日 • 用户投稿
    000
  • Epic禁止自动启动设置_开机不启动Epic解决方案

    Epic禁止自动启动设置_开机不启动Epic解决方案Epic禁止自动启动设置_开机不启动Epic解决方案Epic禁止自动启动设置_开机不启动Epic解决方案Epic禁止自动启动设置_开机不启动Epic解决方案

    可通过客户端设置、任务管理器、启动文件夹或注册表编辑器禁用Epic自动启动。首先在Epic设置中关闭“启动时启动”选项;其次在任务管理器“启动”选项卡中禁用Epic Games Launcher;然后检查并删除“shell:startup”启动文件夹中的相关快捷方式;最后通过注册表编辑器删除HKEY…

    2026年9月26日 • 用户投稿
    100
  • Java项目质量保障体系:静态分析、单元测试与集成测试

    Java项目质量保障体系:静态分析、单元测试与集成测试Java项目质量保障体系:静态分析、单元测试与集成测试Java项目质量保障体系:静态分析、单元测试与集成测试Java项目质量保障体系:静态分析、单元测试与集成测试

    静态分析是Java质量保障的第一道防线,因其能在代码运行前发现潜在缺陷。SonarQube等工具通过集成Checkstyle、PMD等规则集,实现代码规范、安全、性能的全面扫描,及早暴露空指针、资源泄漏等问题,减少技术债。它作为“预检系统”,避免低级错误流入后续阶段,提升整体代码整洁度,为单元与集成…

    2026年9月26日 • 用户投稿
    000
  • 如何解决MySQL版本兼容性问题的处理方法?

    如何解决MySQL版本兼容性问题的处理方法?如何解决MySQL版本兼容性问题的处理方法?如何解决MySQL版本兼容性问题的处理方法?如何解决MySQL版本兼容性问题的处理方法?

    mysql版本兼容性问题可通过升级、降级或编写兼容代码解决。具体步骤为:1.明确问题根源,如sql语法、函数或协议不兼容;2.选择升级或降级版本,优先考虑升级以获取优化和修复;3.使用注释语法编写兼容性sql;4.借助orm框架屏蔽底层差异;5.通过查询版本号或配置文件实现条件判断;6.利用dock…

    2026年9月26日 • 用户投稿
    100
  • 悟空浏览器怎么设置鼠标手势_悟空浏览器鼠标手势功能开启与自定义

    悟空浏览器怎么设置鼠标手势_悟空浏览器鼠标手势功能开启与自定义悟空浏览器怎么设置鼠标手势_悟空浏览器鼠标手势功能开启与自定义悟空浏览器怎么设置鼠标手势_悟空浏览器鼠标手势功能开启与自定义悟空浏览器怎么设置鼠标手势_悟空浏览器鼠标手势功能开启与自定义

    悟空浏览器可通过开启鼠标手势提升操作效率,依次在设置中启用功能、查看默认手势、添加自定义轨迹并绑定命令,还可修改或删除已有手势以优化使用体验。 如果您希望在浏览网页时通过鼠标滑动快速执行常用操作,悟空浏览器的鼠标手势功能可以显著提升您的操作效率。启用并自定义鼠标手势后,您可以通过特定的鼠标轨迹快速返…

    2026年9月26日 • 用户投稿
    000
  • 豌豆素质如何退费

    豌豆素质如何退费豌豆素质如何退费豌豆素质如何退费豌豆素质如何退费

    在选择教育课程时,退费问题一直是大家关注的焦点。对于豌豆素质的退费流程,很多家长都希望能有一个全面清晰的了解。 首先,要明确退费的条件。一般来说,如果在课程未开始前申请退费,通常是比较容易办理的。比如因为个人时间安排冲突,提前向豌豆素质官方客服说明情况,经过核实后,会按照一定比例退还已缴纳的费用。 …

    2026年9月26日 • 用户投稿
    000
  • sublime怎么设置成中文界面_sublime界面语言切换为中文教程

    sublime怎么设置成中文界面_sublime界面语言切换为中文教程sublime怎么设置成中文界面_sublime界面语言切换为中文教程sublime怎么设置成中文界面_sublime界面语言切换为中文教程sublime怎么设置成中文界面_sublime界面语言切换为中文教程

    通过Package Control安装ChineseLocalization或Simplified Chinese Language插件;2. 若不可用则手动下载GitHub汉化包并复制到Packages目录;3. 重启后通过命令面板选择中文语言,实现界面中文化。 Sublime Text 默认不支…

    2026年9月26日 • 用户投稿
    100
  • win10系统中cortana无法工作怎么解决

    win10系统中cortana无法工作怎么解决win10系统中cortana无法工作怎么解决win10系统中cortana无法工作怎么解决win10系统中cortana无法工作怎么解决

    我们知道,在windows 10系统中内置了一个非常有趣的智能语音助手——cortana(也被亲切地称为“小娜”)。当我们想快速找到某个应用程序,却不想手动逐个查找时,只需向“小娜”发出指令,她就能迅速告诉我们应用的位置,使用起来十分便捷。然而,最近有用户反馈说在使用过程中遇到了cortana无法正…

    2026年9月26日 • 用户投稿
    200
  • 对象的内存布局是怎样的?(对象头、实例数据、对齐填充)

    对象的内存布局是怎样的?(对象头、实例数据、对齐填充)对象的内存布局是怎样的?(对象头、实例数据、对齐填充)对象的内存布局是怎样的?(对象头、实例数据、对齐填充)对象的内存布局是怎样的?(对象头、实例数据、对齐填充)

    JVM中对象内存布局由对象头、实例数据和对齐填充三部分组成,对象头存储Mark Word和类型指针,实例数据按字段大小排序存放以优化对齐,对齐填充保证对象大小为8字节倍数以提升访问效率。 在Java虚拟机(JVM)中,一个对象在内存中的布局通常可以划分为三个主要部分:对象头(Object Heade…

    2026年9月26日 • 用户投稿
    200
  • 【Tools】 一款方便 Windows 桌面运维的计算机信息收集和在线检测工具

    【Tools】 一款方便 Windows 桌面运维的计算机信息收集和在线检测工具【Tools】 一款方便 Windows 桌面运维的计算机信息收集和在线检测工具【Tools】 一款方便 Windows 桌面运维的计算机信息收集和在线检测工具【Tools】 一款方便 Windows 桌面运维的计算机信息收集和在线检测工具

    简介 这是一款专为windows桌面运维设计的计算机信息采集与在线状态检测工具,可自动获取主机名、当前用户名、cpu型号、内存容量、硬盘使用情况、ip地址、mac地址等关键硬件和网络信息。 功能特点: 支持系统托盘运行模式 客户端可设置静默启动 支持定时向服务端上报设备信息 服务端配备图形化管理界面…

    2026年9月26日 • 用户投稿
    200
  • 夸克88VIP送的会员怎么领取_88VIP赠送夸克会员兑换流程

    夸克88VIP送的会员怎么领取_88VIP赠送夸克会员兑换流程夸克88VIP送的会员怎么领取_88VIP赠送夸克会员兑换流程夸克88VIP送的会员怎么领取_88VIP赠送夸克会员兑换流程夸克88VIP送的会员怎么领取_88VIP赠送夸克会员兑换流程

    首先通过淘宝App进入“我的淘宝”-“88VIP”-“其他权益”,找到夸克网盘会员并绑定手机号完成领取;若未到账,需打开夸克App进入“会员中心”同步权益;确保淘宝与夸克登录手机号一致,避免领取失败。 如果您是淘宝88VIP会员,并希望领取夸克网盘提供的专属会员权益,但不清楚具体操作流程,可能会导致…

    2026年9月26日 • 用户投稿
    100
  • sublime怎么在mac上设置命令行工具_sublime Mac命令行工具配置

    sublime怎么在mac上设置命令行工具_sublime Mac命令行工具配置sublime怎么在mac上设置命令行工具_sublime Mac命令行工具配置sublime怎么在mac上设置命令行工具_sublime Mac命令行工具配置sublime怎么在mac上设置命令行工具_sublime Mac命令行工具配置

    首先确认Sublime可执行路径为/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl,接着创建软链接sudo ln -s /Applications/Sublime Text.app/Contents/SharedSuppor…

    2026年9月26日 • 用户投稿
    100
  • 可以穿梭时空的实时计算框架——Flink对时间的处理

    可以穿梭时空的实时计算框架——Flink对时间的处理可以穿梭时空的实时计算框架——Flink对时间的处理可以穿梭时空的实时计算框架——Flink对时间的处理可以穿梭时空的实时计算框架——Flink对时间的处理

    Flink对于流处理架构的意义十分重要,Kafka让消息具有了持久化的能力,而处理数据,甚至穿越时间的能力都要靠Flink来完成。 在streaming-大数据的未来一文中我们知道,对于流式处理最重要的两件事,正确性,时间推理工具。而flink对两者都有非常好的支持。 Flink对于正确性的保证 对…

    2026年9月26日 • 用户投稿
    300
  • 拼多多床退了运费200多退吗?大件让我承担运费咋办?拼多多大件退货必看!200元运费这样退,维权攻略全解析!

    拼多多床退了运费200多退吗?大件让我承担运费咋办?拼多多大件退货必看!200元运费这样退,维权攻略全解析!拼多多床退了运费200多退吗?大件让我承担运费咋办?拼多多大件退货必看!200元运费这样退,维权攻略全解析!拼多多床退了运费200多退吗?大件让我承担运费咋办?拼多多大件退货必看!200元运费这样退,维权攻略全解析!拼多多床退了运费200多退吗?大件让我承担运费咋办?拼多多大件退货必看!200元运费这样退,维权攻略全解析!

    在拼多多购买床垫、沙发等大件商品后,若遭遇退货需自付200多元运费的情况,该如何应对?平台对此有何明确规定?本文将深入解读大件商品退货运费的责任归属规则,明确哪些情形下可主张由商家承担运费,哪些情况必须自行支付。同时提供一套完整的维权操作流程,涵盖证据留存、平台申诉及法律手段,一步步教你解决高额退货…

    2026年9月26日 • 用户投稿
    300
  • Safari浏览器如何重置到初始设置_Safari浏览器恢复默认出厂设置操作

    Safari浏览器如何重置到初始设置_Safari浏览器恢复默认出厂设置操作Safari浏览器如何重置到初始设置_Safari浏览器恢复默认出厂设置操作Safari浏览器如何重置到初始设置_Safari浏览器恢复默认出厂设置操作Safari浏览器如何重置到初始设置_Safari浏览器恢复默认出厂设置操作

    重置Safari可解决运行缓慢、加载异常等问题。首先通过Safari偏好设置清除历史记录与网站数据,并恢复各项功能至默认值;若问题依旧,可使用终端命令删除偏好文件及缓存实现深度重置;也可通过系统设置一次性清除所有浏览数据与扩展信息,重启后恢复初始状态。 如果您发现Safari浏览器运行缓慢、页面加载…

    2026年9月26日 • 用户投稿
    100

发表回复

登录后才能评论
关注微信