处理Hutool的Http工具上传大文件报OOM
程序环境
- JDK版本: 1.8
- Hutool版本: 5.8.25
问题描述
客服端文件上传主要代码:
HttpRequest httpRequest = HttpUtil.createPost(FILE_UPLOAD_URL);
Resource urlResource = new UrlResource(url, fileName);
httpRequest.form("file", urlResource);
HttpResponse httpResponse = httpRequest.execute();
大文件上传 java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:3236) ~[na:1.8.0_275]at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118) ~[na:1.8.0_275]at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93) ~[na:1.8.0_275]at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:135) ~[na:1.8.0_275]at sun.net.www.http.PosterOutputStream.write(PosterOutputStream.java:63) ~[na:1.8.0_275]at cn.hutool.http.MultipartOutputStream.write(MultipartOutputStream.java:108) ~[hutool-all-5.8.25.jar!/:5.8.25]at java.io.OutputStream.write(OutputStream.java:116) ~[na:1.8.0_275]at cn.hutool.core.io.copy.StreamCopier.doCopy(StreamCopier.java:102) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.copy.StreamCopier.copy(StreamCopier.java:68) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:162) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:146) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:132) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:119) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.resource.Resource.writeTo(Resource.java:76) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.MultipartOutputStream.appendResource(MultipartOutputStream.java:163) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.MultipartOutputStream.write(MultipartOutputStream.java:96) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.body.MultipartBody$$Lambda$2190/568941495.accept(Unknown Source) ~[na:na]at cn.hutool.core.map.TableMap.forEach(TableMap.java:253) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.body.MultipartBody.write(MultipartBody.java:78) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.body.RequestBody.writeClose(RequestBody.java:27) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.sendMultipart(HttpRequest.java:1402) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.send(HttpRequest.java:1340) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.doExecute(HttpRequest.java:1188) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.execute(HttpRequest.java:1051) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.execute(HttpRequest.java:1027) ~[hutool-all-5.8.25.jar!/:5.8.25]at com.mbzj.ai.third.RhzClient.execute(RhzClient.java:270) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.third.RhzClient.uploadKnowledgeFile(RhzClient.java:184) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.third.RhzService.uploadKnowledgeFile(RhzService.java:132) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.listener.KnowledgeFileListener.handleAddKnowledgeFileEvent(KnowledgeFileListener.java:64) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.listener.KnowledgeFileListener$$FastClassBySpringCGLIB$$beafef7e.invoke(<generated>) ~[classes!/:1.0-SNAPSHOT]at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.28.jar!/:5.3.28]at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.28.jar!/:5.3.28]
分析问题
从异常堆栈信息中可以看出这里使用了 java.io.ByteArrayOutputStream 。实际上就是把文件全部都加载到了Byte数组中,如果上传的文件过大必定会导致OOM。
hutool httpRequest执行流程
这里实际上是使用的 java.net.HttpURLConnection。
解决方案
java.net.HttpURLConnection 是支持 StreamingMode 传输HTTP请求的,有两种方式开启:
- setFixedLengthStreamingMode
当预先知道内容长度时,该方法用于使得能够在没有内部缓冲的情况下流式传输HTTP请求主体。
如果应用程序尝试写入比指示的content-length更多的数据,或者如果应用程序在写入指示的数量之前关闭OutputStream,则将引发异常。 - setChunkedStreamingMode
当内容长度为不提前知道。在这种模式下,使用分块传输编码来发送请求正文。请注意,并非所有HTTP服务器都支持此模式。
启用输出流时,无法自动处理身份验证和重定向。如果需要身份验证或重定向,则读取响应时将引发HttpRetryException。
Hutool 的 HttpRequest中只提供了 setChunkedStreamingMode方式,setFixedLengthStreamingMode 方式其实感觉上会更好,不会出现服务端不支持的情况,作者表示下一版本中将会支持setFixedLengthStreamingMode 。
先来测试一下 setChunkedStreamingMode 的效果。
这里自己写一个服务端的接口看看StreamingMode的header有什么区别。
@PostMapping("test")
public void test(MultipartFile file, HttpServletRequest request) {System.out.println("fileSize" + file.getSize());// 打印所有headerEnumeration<String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();System.out.println(name + ":" + request.getHeader(name));}
}
这是修改前会出现OOM的客户端代码
HttpRequest httpRequest = HttpUtil.createPost("http://127.0.0.1:8064/test");
URL fileUrl = new URL("https://xxxx/1a67c727f8a845dd8b0b9825026349dd.mp4");
UrlResource urlResource = new UrlResource(fileUrl, "test.mp4");
httpRequest.form("file", urlResource);
System.out.println(httpRequest);
HttpResponse httpResponse = httpRequest.execute();
System.out.println(httpResponse);
堆内存明显增高
服务端日志输出:
accept:text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 Hutool
accept-encoding:gzip, deflate
content-type:multipart/form-data; boundary=--------------------Hutool_rV0KKNQCkTkwywrQ
cache-control:no-cache
pragma:no-cache
host:127.0.0.1:8064
connection:keep-alive
content-length:128553150
客户端上传日志:
Request Url: http://127.0.0.1:8064/ai/knowledge/test
Request Headers: Accept: text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 HutoolAccept-Encoding: gzip, deflate
Request Body: file=https%3A%2F%2Fcos-uclass.lconrise.cn%2Fbiz%2Fai%2Fknowledge%2Ffile%2F1a67c727f8a845dd8b0b9825026349dd.mp4Response Headers: Keep-Alive=[timeout=60]X-Frame-Options=[DENY]null=[HTTP/1.1 200]Cache-Control=[no-cache, no-store, max-age=0, must-revalidate]X-Content-Type-Options=[nosniff]Connection=[keep-alive]Expires=[0]Pragma=[no-cache]Content-Length=[0]X-XSS-Protection=[1; mode=block]Date=[Wed, 11 Sep 2024 01:59:55 GMT]
Response Body:
客户端通过 setChunkedStreamingMode 开启 StreamingMode:
HttpRequest httpRequest = HttpUtil.createPost("http://127.0.0.1:8064/ai/knowledge/test");
URL fileUrl = new URL("https://cos-uclass.lconrise.cn/biz/ai/knowledge/file/1a67c727f8a845dd8b0b9825026349dd.mp4");
UrlResource urlResource = new UrlResource(fileUrl, "test.mp4");
httpRequest.form("file", urlResource);
httpRequest.setChunkedStreamingMode(1024 * 8);
System.out.println(httpRequest);
HttpResponse httpResponse = httpRequest.execute();
System.out.println(httpResponse);
上传文件时堆内存无明细变化:
服务端日志输出:
accept:text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 Hutool
accept-encoding:gzip, deflate
content-type:multipart/form-data; boundary=--------------------Hutool_Zn5eac5m74pQH1IJ
cache-control:no-cache
pragma:no-cache
host:127.0.0.1:8064
connection:keep-alive
transfer-encoding:chunked
客户端上传日志:
Request Url: http://127.0.0.1:8064/ai/knowledge/test
Request Headers: Accept: text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 HutoolAccept-Encoding: gzip, deflate
Request Body: file=https%3A%2F%2Fcos-uclass.lconrise.cn%2Fbiz%2Fai%2Fknowledge%2Ffile%2F1a67c727f8a845dd8b0b9825026349dd.mp4Response Headers: Keep-Alive=[timeout=60]X-Frame-Options=[DENY]null=[HTTP/1.1 200]Cache-Control=[no-cache, no-store, max-age=0, must-revalidate]X-Content-Type-Options=[nosniff]Connection=[keep-alive]Expires=[0]Pragma=[no-cache]Content-Length=[0]X-XSS-Protection=[1; mode=block]Date=[Wed, 11 Sep 2024 02:02:28 GMT]
Response Body:
正常上传请求包含 content-lengt
header, 来告诉服务端当前请求主体内容的字节数。
StreamingMode
中 没有 content-length
,而是新增了 transfer-encoding:chunked
。
扩展
-
Transfer-Encoding: chunked:
- 这是一种 HTTP 传输编码,允许服务器在不知道整个响应内容长度的情况下,分批次发送数据。
- 每个数据块前会有一个指定大小的头部,表明该块的大小,直到遇到大小为
0
的块,表示传输结束。
-
服务端处理:
- 服务端(如 Tomcat)在接收到
chunked
编码的请求时,会按照分块传输编码的规则来读取数据。 - 服务端会持续读取数据块,直到检测到一个大小为
0
的块,这表示输入流已经结束。
- 服务端(如 Tomcat)在接收到
-
Tomcat 配置:
- Tomcat 允许通过配置
<Connector>
标签的maxPostSize
属性来限制请求体的最大大小。 fileSizeThreshold
参数定义了上传文件写入磁盘的阈值,这对于处理大文件上传尤为重要。
- Tomcat 允许通过配置
-
流式上传:
- Tomcat 支持流式上传,这意味着数据可以边读边写,不需要将整个文件内容一次性加载到内存中。
- 流式上传适用于大文件或实时数据传输,如视频流。
-
异步处理:
- Tomcat 支持 Servlet 3.0 规范中的异步处理机制,允许长时间运行的操作在单独的线程中执行。
- 这可以提高 Tomcat 的并发处理能力和系统吞吐量。
-
异常处理:
- 在文件上传过程中,如果出现异常(如文件大小超出限制),Tomcat 会抛出相应的异常。
- 开发者需要在代码中妥善处理这些异常,并在必要时进行异常捕获和处理。
-
请求结束:
- 处理完所有数据块后,Tomcat 会关闭输入流,并根据请求的内容执行相应的业务逻辑。
用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding
用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding
HTTP响应字段Transfer-Encoding含义及作用详解
相关文章:
处理Hutool的Http工具上传大文件报OOM
程序环境 JDK版本: 1.8Hutool版本: 5.8.25 问题描述 客服端文件上传主要代码: HttpRequest httpRequest HttpUtil.createPost(FILE_UPLOAD_URL); Resource urlResource new UrlResource(url, fileName); httpRequest.form("file&q…...
transforms的使用
示例代码 from PIL import Image from torch.utils.tensorboard import SummaryWriter from torchvision import transforms#打开该图片 img_path"hymenoptera_data/val/bees/10870992_eebeeb3a12.jpg" imgImage.open(img_path) writerSummaryWriter("logs&quo…...
python-PyQt项目实战案例:制作一个视频播放器
文章目录 1. 关键问题描述2. 通过OpenCV读取视频/打开摄像头抓取视频3. 通过PyQt 中的 QTimer定时器实现视频播放4. PyQt 视频播放器实现代码参考文献 1. 关键问题描述 在前面的文章中已经分享了pyqt制作图像处理工具的文章,也知道pyqt通过使用label控件显示图像的…...
反向传播的微积分原理 | Chapter 4 | Deep Learning | 3Blue1Brown
目录 前言1. 简介2. 神经网络中的链式法则3. 微积分的计算4. 公式含义5. 代价函数对权重偏置的敏感度6. 多个神经元的情形7. 回顾相关资料结语 前言 3Blue1Brown 视频笔记,仅供自己参考 这个章节主要来深度讲解反向传播中的一些微积分理论 官网:https://…...
matlab读取excel表格
使用matlab读取excel表格中的数据 使用推荐代码读取excel表格中的数据 path "C:\Users\24975\Desktop\503\GUI展示案例\Tx_20_0_Rx_40_90_0.1_95_L.xlsx";%文件路径 data readtable(path,Sheet,Sheet1,ReadRowNames,false,ReadVariableNames,false,Ra…...
基于springboot+vue实现的助学兼职系统(源码+L文+ppt)4-092
基于springbootvue实现的助学兼职系统(源码L文ppt)4-092 第4章 系统设计 4.1 总体功能设计 一般学生、招聘公司和管理者都需要登录才能进入助学兼职系统,使用者登录时会在后台判断使用的权限类型,包括一般使用者和管理者,一般使…...
⌈ 传知代码 ⌋ 农作物病害分类(Web端实现)
💛前情提要💛 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间,对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…...
CMU生成式人工智能大模型:从入门到放弃(九)
引言 在前面的系列博客中,我们深入探讨了生成式对抗网络(GANs)和变分自编码器(VAEs)等生成式模型。今天,我们将探索扩散模型(Diffusion Models)的进一步应用,并讨论在上…...
HTML基础总结
一、简介 HTML(HyperText Markup Language)即超文本标记语言,是用于创建网页的标准标记语言。它通过使用各种标签来定义网页的结构和内容,告诉浏览器如何显示网页。HTML 文档由标签和文本组成,标签用于描述文本的性质…...
EXCELL中如何两条线画入一张图中,标记坐标轴标题?
1,打开excel,左击选中两列, 2,菜单栏>“插入”>”二维折线图”选中一个 3,选中出现的两条线中的一条右击>最下一行,“设置数据系列格式” 4,右测“系列选项中”>点击“次坐标轴” 5…...
Zabbix企业级分布式监控环境部署
“运筹帷幄之中,决胜千里之外”。在IT运维中,监控占据着重要的地位,按比例来算,说占30%一点也不为过。对IT运维工程师来说,构建一个真正可用的监控告警系统是一项艰巨的任务。在监控系统的开源软件中,可供选…...
水轮发电机油压自动化控制系统解决方案介绍
在现代水电工程中,水轮机组油压自动化控制系统,不仅直接关系到水轮发电机组的安全稳定运行,还影响着整个水电站的生产效率和经济效益。 一、系统概述 国科JSF油压自动控制系统,适用于水轮发电机组调速器油压及主阀(蝶…...
今天不分享技术,分享秋天的故事
引言 这个爱情故事好像是个悲剧,你说的是婚姻。爱情没有悲剧,对爱者而言,爱情怎么会是悲剧呢。对春天而言,秋天是它的悲剧吗。结尾是什么,等待,之后呢,没有之后。或者说,等待的结果…...
转录组上游分析流程(三)
环境部署——数据下载——查看数据(非质控)——数据质控——数据过滤(过滤低质量数据) 测序得到的原始序列含有接头序列和低质量序列,为了保证信息分析的准确性,需要对原始数据进行质量控制,得到高质量序列(Clean Reads),原始序列…...
excel判断某一列(A列)中的数据是否在另一列(B列)中
如B列如果有7个元素,在A列右边的空白列中,输入如下公式: COUNTIF($B$1:$B$7,A1), 其中,$B$1:$B$7代表A列中的所有数据即绝对范围,A1代表B列中的一个单元格....
[环境配置]macOS上怎么查看vscode的commit id
macOS的commit id和windows上有点不一样,windows可以在帮助-关于查看 macOS则需要再左边第一个查看...
.net framework 3.5sp1组件安装进度条不动启动错误怎么解决
安装.NET Framework 3.5 SP1通常需要管理员权限。这是因为安装过程可能需要修改系统文件和注册表项,这些操作通常需要管理员权限才能执行。在Windows系统上,安装.NET Framework 3.5 SP1通常通过控制面板中的“启用或关闭Windows功能”选项进行࿰…...
学习threejs,利用THREE.ExtrudeGeometry拉伸几何体实现svg的拉伸
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.ExtrudeGeometry拉伸…...
大模型之三十二-语音合成TTS(coqui) 之二 fine-tune
在 大模型之三十-语音合成TTS(coqui)[shichaog CSDN]中提到了xttsv2的fine-tune。 数据情况: 我是从bilibili up主小Lin说提取了一些视频,然后进行了重新的fine-tune。 训练结果 如下图所示,上面波形幅度较大的是xttsv2原始模型的结果&am…...
JVM的内存模型是什么,每个区域的作用是什么,以及面试题(含答案)
JVM(Java 虚拟机)内存模型定义了 Java 程序在运行时如何分配、管理和优化内存。JVM 内存模型主要分为几个关键区域,每个区域有特定的作用: JVM 内存模型 堆内存(Heap): 作用:用于存…...
《设计模式三》Java代理模式实现
Java代理模式实现 静态代理实现 // Subject.java // 主题接口,定义了请求方法 public interface Subject {void request(); }// RealSubject.java // 真实主题实现类,实现了Subject接口 public class RealSubject implements Subject {Overridepublic …...
vue3中计算属性的用法以及使用场景
在 Vue 3 中,计算属性(computed properties)是一种基于依赖项动态计算并缓存的响应式数据。它与 Vue 2 中的计算属性类似,但在组合式 API 中使用 computed 函数来定义。计算属性的核心优势在于能够自动缓存计算结果,仅…...
pytorh学习笔记——cifar10(六)MobileNet V1网络结构
基础知识储备: 一、深度可分离卷积(Depthwise Separable Convolution) MobileNet的核心是深度可分离卷积(Depthwise Separable Convolution),深度可分离卷积是卷积神经网络(CNN…...
报表系统-连接数据库操作
本专栏用于解析自己开源的项目代码,作为复盘和学习使用。欢迎大家一起交流 本样例说明源码开源在: ruoyi-reoprt gitee仓库 ruoyi-report github仓库 欢迎大家到到项目中多给点star支持,对项目有建议或者有想要了解的欢迎一起讨论 连接数据库…...
[计算机网络] 常见端口号
前言 常见的端口号是指互联网协议(如TCP/IP)中预留给特定服务使用的数字范围。它们主要用于标识网络应用程序和服务,并帮助数据包在网络中找到正确的接收方。 按协议类型划分 TCP协议端口: 21:FTP文件传输协议2…...
Linux系统块存储子系统分析记录
1 Linux存储栈 通过网址Linux Storage Stack Diagram - Thomas-Krenn-Wiki-en,可以获取多个linux内核版本下的存储栈概略图,下面是kernel-4.0的存储栈概略图: 2 存储接口、传输速度 和 协议 2.1 硬盘 《深入浅出SSD:固态存储核心…...
大数据——本地威胁检测的全球方法
大数据似乎是众多专业人士关注的话题,从在自然灾害发生时帮助挽救生命,到帮助营销团队设计更有针对性的策略以接触新客户。 对于安全工程师来说,大数据分析被证明是抵御不断演变的网络入侵的有效防御手段,这得益于基于大量不同网…...
使用postman接口测试
一 、postman断言 1、什么是断言 postman 断言借助JavaScript -js 语言编写代码,自动判断预期结果与实际结果是否一致。 断言代码写在 Tests 的标签中。(新版本在Scripts标签中) 2、断言工作原理 3、常用断言 断言响应状态码 // 断言响应状态码 是否为 200 pm.…...
Ubuntu24.04双系统安装(Linux/windows共存一文打通)
他向远方望去,无法看到高山背后的矮山,只能看到一座座更高的山峰。 目录 编辑 一.前言 二.虚拟机和双系统比较 三.Windows/Linux双系统安装 1.Rufus-制作U盘启动盘系统工具安装 2.Ubuntu24.04下载 3.Ubuntu-u盘启动盘制作 4.压缩磁盘留足安装空…...
C++ - deque
博客主页:【夜泉_ly】 本文专栏:【C】 欢迎点赞👍收藏⭐关注❤️ 文章目录 💡双端队列简介1. 基本特性2. 与其他容器的比较与 vector与 list 3. 中控数组的设计4. 优缺点优点缺点 5. 应用场景6. 结论 💡双端队列简…...
网站建设属于什么支出/杭州seo排名优化外包
为什么80%的码农都做不了架构师?>>> 常见的数据库优化方法:索引(数据库),缓存,分表,分库,sql优化。 索引:创建索引一般有以下两个目的:维护被索引…...
网站不加www/给公司做网站要多少钱
伺服驱动器的工作原理及伺服驱动器的常见接线方法: 伺服驱动器在控制信号的作用下驱动执行电机,因此驱动器是否能正常工作直接影响设备的整体性能。在伺服控制系统中,伺服驱动器相当于大脑,执行电机相当于手脚。而伺服驱动器在伺服…...
中国最大的库存尾货清货平台/seo关键词排名优化品牌
近来公司redmine服务器表现很糟糕,在16核,64GRAM的机器上,压测结果竟然只有每秒5~7个请求,部分页面一个都出不来。 以下是我对Redmine性能优化方案: redmine服务器性能问题排查与优化建议: 以下建议的方案是基于redmi…...
做网站好还是做微信小程序好/防疫测温健康码核验一体机
利用TreeView控件和ImageList控件显示我的电脑的结构目录:我的电脑-驱动器-文件夹,程序运行结果如下图所示。 程序代码如下。 using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin…...
上海推广有限公司/北京seo学校
题目描述 太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都…...
网站建设公司 倒闭/百度指数怎么提升
如果在使用UIAlertView的过程中,莫名其妙的出现wait_fences: failed to receive reply: 10004003这个错误,那么十有八九是因为你忘记了关闭键盘。 UIAlertView一弹出,倘若键盘没有关闭,就失去了焦点,当UIAlertView关闭…...