• 关于 编码方案如何看配置 的搜索结果

问题

Nginx性能为什么如此吊

小柒2012 2019-12-01 21:20:47 15038 浏览量 回答数 3

问题

wttr.in 一个 Python 实现的命令行查看天气工具

huc_逆天 2020-05-21 19:12:17 19 浏览量 回答数 1

回答

iperf,具体要纤细直接去看文档, 简单给你列条测试:(TCP和UDP知只是两种传输数据的协议) 1)TCP测试    服务器执行:./iperf -s -i 1 -w 1M '这裏是指定windows如果是 iperf -s则windwos默认大小为8kbyte/s    客户端执行:./iperf -c host -i 1 -w 1M   其中-w表示TCP window size,host需替换成服务器地址。    2)UDP测试    服务器执行:./iperf -u -s    客户端执行:./iperf -u -c 10.255.255.251 -b 900M -i 1 -w 1M -t 60   其中-b表示使用多少带宽,1G的线路你可以使用900M进行测试。 不给分不给力 连接速度是个很怪的概念。我们通常用连接带宽和网络延迟来表达网络连接的状态。 带宽可以用一端建立FTP服务器,另一端下载来测试。网络延时可以用PING命令来测试。 希望能帮到你。 行的。 家庭或小型办公室,如果有两台或更多的计算机,很自然地希望将他们组成一个网络。为方便叙述,以下约定将其称为局域网。在家庭环境下,可用这个网络来共享资源、玩那些需要多人参与的游戏、共用一个调制解调器享用Internet连接等等。办公室中,利用这样的网络,主要解决共享外设如打印机等,此外,办公室局域网也是多人协作工作的基础设施。 别看这样小的网络工程,在过去也是需要专业人员来进行组网配置的。那时,大部分操作的都是手工的,一般的用户都不具备相应的知识和经验。正好属于"高不成低不就"的情况,自然限制了它的发展。Windows XP的出现,打破了这种局面,这依赖它内建有强大的网络支持功能和方便的向导。用户完成物理连接后,运行连接向导,可以自己探测出网络硬件、安装相应的驱动程序或协议,并指导用户,完成所有的配置步骤。 本文介绍两种在Windows XP操作系统下的组网方案,并介绍Windows XP用于局域网中的各种很有特色的功能。 一. 目标: 组成家庭局域网:对外,可以连接Internet,允许局域网内的各个计算机共享连接。对内,可以共享网络资源和设备。 二. 采用什么网络形式? 家庭网中的计算机可能有桌面机或便携机,例如掌上电脑或笔记本机等,也可能出现各种传输介质的接口,所以网络形式上,不宜都采用有线网络,无线接口是必须考虑的。但如果可以明确定位在纯粹的有线网上,也可不设无线接口。所以,这里提供两种方案: 1. 有线与无线混合。 2. 有线。 三. 网络硬件选择 网络适配器(网卡)可采用PCI、PC或PCMCIA接口的卡(后两者多用在便携式机或笔记本机上),Windows XP也支持用USB接口的网络适配器。究竟采用那种适配器,取决于接入网络中的计算机。无论那种适配器,都需要注意与现有计算机的接口以及HUB的协调一致,USB接口的适配器可能适应性更强一些,但对于较旧的计算机,又需要注意它是否支持USB接口。 网络连接线,常用的有同轴电缆和双绞线,这都是大家熟悉的东西,不多解释。究竟采用哪一种,就看你怎么想了。 四. 可采用的网络结构和介质 以太结构:这种结构在办公室或商业用户中最为流行,熟悉的人也很多,技术资料和维护人员也容易找到,所以不多赘述。 电话线连接:这种形式主要的特色是成本很低,物理连接也很简单,适用于大部分的家庭用户。 无线电波:利用电磁波信号来传输信号,可以不用任何连线来进行通讯,并可以在移动中使用。但需要在每台计算机上加装无线适配器,成本高是肯定了。在我国,无线形式用在计算机网络通讯的还较少。在美国,用于无线网络的是一个称为IEEE 802.11b的标准协议,用于计算机近距离网络通讯。在该协议支持下,可达到的网速是11 Mbps。 五. 方案之一 这是一个有线、无线混合方案,具体结构可以参看图1。这个例子中,用4台计算机组成了一个混合网络,PC1是主机,它与外部连接有3个通路: 1. 与Internet接连的调制解调器:用于整个网络的各个计算机共享上网之用。 2. 无线适配器:用于和本网络内的无线设备之间的通讯。 3. HUB:用于"带动"本网络内的下游计算机。 该方案中的PC1、PC2机,必须用Windows XP操作系统,有线部分采用的是以太网结构连接。图中的HPNA是home phoneline network adaptor的缩写,表示家庭电话线网络适配器。图中的PC3和移动计算机,并不要求非使用Windows XP操作系统不可,别的windows版本也行。移动计算机和主机之间的网络连接利用的是无线形式。 如果希望建立混合网络,这种方案已经具备典型的功能,并且不需要花费很大就可以扩充网络规模。 关于连通操作: 图1显示的结构只能表示物理连接关系,物理连接完成后,还需要进行连通操作,网络才可真正投入使用。连通操作包括局域网内部各个计算机之间的连通,和局域网与Internet之间的连通。前者连通建立的步骤如下: 1. 鼠标点击 开始,进入控制面板,点击"Network and Internet Connections网络和Internet连接",选择网络连接( Network Connections),进行下一步。 2. 选择进行"两个或多个LAN的连接" 3. 右键点击一个连接. 4. 确定完成连接任务. 局域网之内的连通操作就完成了。 再说局域网与Internet之间的连通,这种情况主要考虑速度与成本两方面的兼顾。多机上网,最省事的办法是每个机器占据一条独立的电话线,但这不是一般用户能承受起的,资源的浪费也太大。另一个办法,可以使用住宅网关,但这样成本需要增加,不是最佳途径。比较好的方法是使用一个计算机作为主机服务器。这不仅技术上可行,还有很多别的优点,如: ①:由于Windows XP有内建的防火墙,主机介于Internet和终端机之间,可以利用主机的防火墙保护局域网中的分机免受来自Internet的攻击。 ②:主机是"隐匿在" Internet和局域网之间的,充当了网关的脚色,在分机上,用户感觉好像自己是直接连在Interne上一样,察觉不到中间还有主机存在。特别是可以使局域网中的每台计算机同时上网。大大减少了设备投资。 ③:除主机必须使用Windows XP操作系统之外,局域网内的计算机可使用早期的windows版本。 ④:如果局域网中需要使用不同的媒体(例如有线和无线混合),可以利用Windows XP作为过渡的网桥。 ⑤:虽然有网络资源和设备的共享功能,但也可以限制别人对私有文件和数据的访问,特别是将文件存放在主机上的时候,更具有这种优势可用。 ⑥:利用"万能即插即用"功能,可以随时扩充局域网的规模。 六. 方案之二 下面是这种方案的结构示意图。该方案适用于小型办公室。与上一个方案比较,主要是去掉了无线部分,主机与分机之间不采用电话线连接,而是采用了电缆或双绞线连接。所有分机都通过一个HUB与主机连接到Internet上,并可以支持打印机共享。这其实就是最常见的那种局域网的结构。 该方案完成物理连接之后,还需要进行下列操作: 1. 打开网络连接文件夹或找到网络连接的图标. 2. 右键点击"connection to the Internet you want to share(共享Internet连接)"然后再右键点击"Properties(属性)" 3. 选择"Advanced(高级)"任务条。 4. 选择"Allow other networkusers to connect through this computer′s Internet connection(允许另外用户通过这个计算机连接到Internet)"检查框,并选定。 5. 点击 OK.结束操作。 启用Windows XP的防火墙,必须进行设置,不设置是不起作用的。设置过程: 1.打开网络连接文件夹或找到网络连接的图标. 2.右键点击"connection to the Internet you want to share(共享Internet连接)"然后再右键点击"Properties(属性)" 3.选择"Advanced(高级)"任务条。 4. 选择"Protect my computer and network by limitingor preventing access to this computer from the Internet(利用这个计算机限制从Internet进入的访问并保护我的计算机和网络" ,在其下面有一个Internet连接防火墙的检查框,鼠标点击选定。 5. 点击 OK.结束操作。 七. 几点说明 A.主机必须采用Windows XP操作系统,局域网内的计算机可以使用早一些的windows版本,如:windows98、windows ME、windows2000等等。 B.这里提供的是典型的情况,想扩充网络规模基本上可以照此叠加。 C.本文是依据英文测试版本进行的试验,不能保证将来的正式版本。特别是中文正式版本的性能与此完全一致。 参考资料: 创建局域网及配置管理 一.概念: (一).局域网的概念: 局域网做为网络的组成部分,发挥了不可忽视的作用。我们可以用Windows 9X把众多的计算机联系在一起,组成一个局域网,在这个局域网中,我们可以在它们之间共享程序、文档等各种资源,而不必再来回传递软盘;还可以通过网络使多台计算机共享同一硬件,如打印机、调制解调器等;同时我们也可以通过网络使用计算机发送和接收传真,方便快捷而且经济。 局域网是一个范围可大可小、简单的只有2台运行着Windows95的计算机连网(以工作组方式工作),也可以是幅员辽阔的高速ATM网和以太网混合使用、运行多种平台的大型企业。 (二).网络的类型: 1、按网络的地理位置分类 a.局域网(LAN):一般限定在较小的区域内,小于10km的范围,通常采用有线的方式连接起来 b.城域网(MAN):规模局限在一座城市的范围内,10~100km的区域。 c.广域网(WAN):网络跨越国界、洲界,甚至全球范围。 目前局域网和广域网是网络的热点。局域网是组成其他两种类型网络的基础,城域网一般都加入了广域网。广域网的典型代表是Internet网。 (二).硬件指南:网络硬件设备 组成小型局域网的主要硬件设备有网卡、集线器等网络传输介质和中继器、网桥、路由器、网关等网络互连设备。以下主要介绍网卡、集线器等网络传输介质和中继器、网桥、路由器、网关等局域网互连设备。 1.网卡 网卡(Network Interface Card,NIC)也叫网络适配器,是连接计算机与网络的硬件设备。网卡插在计算机或服务器扩展槽中,通过网络线(如双绞线、同轴电缆或光纤)与网络交换数据、共享资源。 Realtek 10/100M,这是我们实例中所使用的网卡 二.组网: 返回顶部 (一).硬件配置:服务器:普通PC机,主板:intel 815,硬盘:迈拓40G,CPU:PIII933,内存:512M ,显示器:ACER。 其他:双绞线一箱(300m),16口HUB一个,RJ45头32个,网卡:Realtek 10/100M 16块。。 由于服务器需要安装两块网卡来用SyGate维护管理,两个网卡的设置请参阅如下的动画。 三.网络维护: 返回顶部 SyGate 4.0是一种支持多用户访问因特网的软件,并且是只通过一台计算机,共享因特网帐号,达到上网的目的。使用SyGate 4.0,若干个用户能同时通过一个小型网络(包括您的笔记本电脑),迅速、快捷、经济地访问因特网。SyGate 4.0能在目前诸多流行的操作系统上运行,譬如:Windows95、Windows98、Windows NT, Windows2000等操作系统;同时,SyGate 4.0还支持多数的因特网连接方式,这包括:调制解调器(模拟线路)拨入、ISDN(综合业务数字网)、线缆调制解调器(Cable Modem)、ADSL以及DirectPC等方式。 SyGate 4.0具有以下优势: 易于安装 SyGate在数分钟之内便可以安装完成,并且通常不需要其他外加的设置。和其他代理服务器软件(proxy server)不同的是,SyGate仅安装Server便可以了。 易于使用 SyGate拥有直观的图形化界面,懂得操作Windows的人员均会操作。SyGate启动后便在后台运行,不需要人工的干预。当SyGate检测到局域网内有上网 要求时,它能自动地连接到因特网上,免去了每次需要手工拨号的烦恼。用户可以不间断地、透明地浏览因特网、收发电子邮件、聊天、使用FTP以及操作其他的小程序等等。局域网内非Windows用户,如Macintosh、Solaris和Linux,均能通过TCP/IP协议上网。 四.Windows 对等网创建与维护 返回顶部 (一).建网软件要求 在一个局域网中,Windows 95、98、NT和2000等操作系统可以并存。当然,即使你的电脑是在DOS下面跑的,也可以实现联网。由于Windows操作系统才是广泛应用的系统,本文不准备讨论DOS联网。 建网硬件要求 要组建电脑网络,无疑需要能将电脑连在一起的硬件设备。最简单的办法是,使用特制的电缆,将两台电脑的并口或者串口联接起来,通过Windows的“直接电缆连接”实现联网。这种联接电缆可以自制,也可以到电脑城购买。其缺点是,只能联接两台电脑,联网距离较短、方式古板,实际应用很不方便,通常要求将一台电脑用作服务器,另外一台用作客户端来实现联网。 但更为普遍采用的是网卡加网线的联网方式。从插槽上分,网卡有ISA和PCI两种;从速度上分,网卡又有10MB和100MB甚至传输速度更高的网卡。要求不高的话,一块PCI 10MB网卡就够用了。 五.疑难解答 返回顶部 (一).网卡安装故障检查方法 如果无法安装网卡驱动程序或安装网卡后无法登录网络,请按下述步骤检查处理: 1.选择“控制面板”/“系统”图标,打开“系统属性”窗口; 2.在“系统属性”窗口的“设备管理”标签的“按类型查看设备列表”中,双击“网络适配器”条目前的“ ”号将其展开,其下应当列出当前网卡; 3.如果“设备管理”标签中没有“网络适配器”条目或当前网卡前有一“X”号,说明系统没能识别网卡,可能产生的原因有网卡驱动程序安装不当、网卡硬件安装不当、网卡硬件故障等等; 参考 LAN(局域网)一词指位于同一区域甚至同一建筑物内的中小型计算机网络,字典上的解释是:将计算机和字处理机等电子办公设备连接在一起构成的办公室或建筑物内的网络系统。相信大多数人都在学校里、当地图书馆或朋友家里。接触过局域网。 随着宽带互联网日益流行,许多人家里都有几台计算机,家庭局域网正在形成规范。通过局域网共享宽带互联网访问可降低成本,不需要每台计算机都连接调制解调器和单独的IP地址。但如何构建一个家庭局域网共享宽带互联网访问呢? 网络带宽表示 网络带宽以兆位秒Mbps测量,通常不用兆字节秒MBps表示。一个字节有八个二进制位组成,多数人都熟悉MBps。当前局域网多为10base-T(10Mbps或1.25MBps)和100base-TX(100Mbps或12.5MBps)的以太网,使用类似标准电话线的RJ-45接口,通过网络电缆把集线器(或路由器、交换器)和计算机连接起来就构成了以太网。 网络布线 开始组建家庭局域网之前,应多少了解一些可用网络电缆的区别。这取决你家中PC机需要安排的位置,因为可能需要在墙上打眼,以穿过五类网络电缆。对家里地方不宽敞的人,这可能是令人畏缩的任务,甚至不太可能。如果你想避免穿墙打眼的麻烦,无线局域网也很方便,但应注意,无线局域网通常速度不够快,花费也高的多。另一种选择可考虑10Mbps电话线套件,利用你现成的电话线在计算机之间传送数据,可购买D-Link,Linksys,3Com和Netgear等公司的产品。不想采用无线局域网的人,可选择五类双绞线网络电缆。如果对电缆不熟悉,下面列出了电子工业协会EIA关于电缆分类的解释。根据电缆的速度和质量,可将电缆分为六类: 一、二类电缆:数据传输速度低于10Mbps(普通电话线) 三类电缆:数据传输速度达16 Mbps 四类电缆:数据传输速度达20 Mbps 五类电缆:数据传输速度达100 Mbps 五类电缆增强:数据传输速度达200 Mbps 六类电缆:数据传输速度达600 Mbps 五类电缆十分普通,连接以太网费用也较低。如果你计划穿墙打眼或使用超过50英尺五类电缆,应购买细电缆,自己动手将RJ-45插头接在电缆两端。注意,别忘了电缆穿过墙之后再接RI-45插头。 连接RJ-45插头 五类电缆连接RJ-45插头并不困难,但需要专用连接工具,可从当地五金商店买一把或从朋友处借用。操作时小心剪掉约1/4英寸电缆外塑料皮,露出电缆里面8根彩色线,注意放入RJ-45连接器里面电缆线的次序: 1、白绿 2、绿 3、白橙 4、兰 5、白兰 6、橙 7、白橙 8、棕 应仔细展开8条彩色编码线,放入RJ-45插孔中,用专用工具压紧。有条件时可用RJ-45测试器验证一下是否连接可靠,以免将来麻烦。 需要的硬件 首先确保每台计算机里都安装了网卡,100base-TX或10base-T网卡,型号、尺寸任意。注意,一般选PCI网卡,各网卡速率应一致。100base-TX网卡数据传输率较高,适合于大量数据传输,如数字电影或其它大的多媒体文件。 组建局域网需要使用集线器,交换器或内置集线器的路由器,集线器只不过用于将你所有的计算机连到局域网上。如果你只有2台计算机并且不打算增加数量,可以用一段电缆直接将2台计算机连起来,缺点是你试图共享宽带互联网访问仍然有麻烦。如果你想多台计算机访问宽带互联网,使用路由器是个好主意,可以选购Netgaer,D-Link和Linksys等著名网络公司的产品。 典型的以太网使用集线器或交换器,两种设备都有单独的连接器,用于将每台计算机连接到局域网上。集线器与交换器的主要差别在于吞吐量,集线器在所有在用的端口间分配吞吐量,因此4端口100base-TX集线器每个在用的端口只有25Mbps吞吐量。交换器更贵些,但允许每个端口全速运行。 假如你准备设置一个只有单个宽带互联网连接的局域网,应确保你的DSL或有线电缆供应商给你提供的是外置调制解调器。多数外置调制解调器通过网卡连接到你的计算机,你可把具有调制解调器的那台计算机设置为路由器,虽然这并不推荐。作为一个例子,你将电话插头接入宽带调制解调器,然后经RJ-45(双绞线)电缆连至集线器/交换器/路由器,从此,你的任一台计算机都可连接到互联网上。 设置Windows网络 确保你准备在局域网上使用的每台计算机,都有足够的五类电缆已连到了集线器或路由器。现在你可能已安装了适当的网卡以及相应的驱动程序,右击“网络邻居”,选择“属性”,可以看到当前已经安装的协议和网卡。要设置网络,应确保所用的网卡已安装了TCP/IP协议。如果你使用的微软操作系统是Windows98或更高版本,网络设置相当简单,Windows网络作为操作系统的基本选项之一应该已经安装了。如果你至少在一台计算机上使用的是Windows Me,你可运行家庭网络向导,将一步步引导你完成设置。记住,你需要使用相同的组名设置你网络中的每台计算机。在Windows95/98中,需要进入网络属性,并确保所有设置为缺省。你的互联网服务供应商ISP可能已经告诉你,如何设置TCP/IP,怎样连接到互联网。你可能是静态IP地址,或是动态IP地址,取决于你的ISP。静态IP地址设置需要的时间稍长一点,如果你想给互联网用户提供服务,如FTP,Web服务器或任何其它服务,静态IP地址是不错的。如果你分配的是IP地址,你的TCP/IP协议属性获得的应是自动选择的IP地址。要检查你的计算机是否已被集线器/路由器分配了一个IP地址,可使用Windows TP配置(进入开始 传输大点的东西,用iostat 1 查看io 来源于网络,供您参考

保持可爱mmm 2019-12-02 02:20:25 0 浏览量 回答数 0

试用中心

为您提供0门槛上云实践机会,企业用户最高免费12个月

问题

MathML 介绍:报错

kun坤 2020-06-08 11:09:17 2 浏览量 回答数 1

回答

92题 一般来说,建立INDEX有以下益处:提高查询效率;建立唯一索引以保证数据的唯一性;设计INDEX避免排序。 缺点,INDEX的维护有以下开销:叶节点的‘分裂’消耗;INSERT、DELETE和UPDATE操作在INDEX上的维护开销;有存储要求;其他日常维护的消耗:对恢复的影响,重组的影响。 需要建立索引的情况:为了建立分区数据库的PATITION INDEX必须建立; 为了保证数据约束性需要而建立的INDEX必须建立; 为了提高查询效率,则考虑建立(是否建立要考虑相关性能及维护开销); 考虑在使用UNION,DISTINCT,GROUP BY,ORDER BY等字句的列上加索引。 91题 作用:加快查询速度。原则:(1) 如果某属性或属性组经常出现在查询条件中,考虑为该属性或属性组建立索引;(2) 如果某个属性常作为最大值和最小值等聚集函数的参数,考虑为该属性建立索引;(3) 如果某属性经常出现在连接操作的连接条件中,考虑为该属性或属性组建立索引。 90题 快照Snapshot是一个文件系统在特定时间里的镜像,对于在线实时数据备份非常有用。快照对于拥有不能停止的应用或具有常打开文件的文件系统的备份非常重要。对于只能提供一个非常短的备份时间而言,快照能保证系统的完整性。 89题 游标用于定位结果集的行,通过判断全局变量@@FETCH_STATUS可以判断是否到了最后,通常此变量不等于0表示出错或到了最后。 88题 事前触发器运行于触发事件发生之前,而事后触发器运行于触发事件发生之后。通常事前触发器可以获取事件之前和新的字段值。语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次。 87题 MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。具体原因为:MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。 86题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 85题 存储过程是一组Transact-SQL语句,在一次编译后可以执行多次。因为不必重新编译Transact-SQL语句,所以执行存储过程可以提高性能。触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。 84题 存储过程是用户定义的一系列SQL语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。 83题 减少表连接,减少复杂 SQL,拆分成简单SQL。减少排序:非必要不排序,利用索引排序,减少参与排序的记录数。尽量避免 select *。尽量用 join 代替子查询。尽量少使用 or,使用 in 或者 union(union all) 代替。尽量用 union all 代替 union。尽量早的将无用数据过滤:选择更优的索引,先分页再Join…。避免类型转换:索引失效。优先优化高并发的 SQL,而不是执行频率低某些“大”SQL。从全局出发优化,而不是片面调整。尽可能对每一条SQL进行 explain。 82题 如果条件中有or,即使其中有条件带索引也不会使用(要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)。对于多列索引,不是使用的第一部分,则不会使用索引。like查询是以%开头。如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引。如果mysql估计使用全表扫描要比使用索引快,则不使用索引。例如,使用<>、not in 、not exist,对于这三种情况大多数情况下认为结果集很大,MySQL就有可能不使用索引。 81题 主键不能重复,不能为空,唯一键不能重复,可以为空。建立主键的目的是让外键来引用。一个表最多只有一个主键,但可以有很多唯一键。 80题 空值('')是不占用空间的,判断空字符用=''或者<>''来进行处理。NULL值是未知的,且占用空间,不走索引;判断 NULL 用 IS NULL 或者 is not null ,SQL 语句函数中可以使用 ifnull ()函数来进行处理。无法比较 NULL 和 0;它们是不等价的。无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。NULL 值可以使用 <=> 符号进行比较,该符号与等号作用相似,但对NULL有意义。进行 count ()统计某列的记录数的时候,如果采用的 NULL 值,会被系统自动忽略掉,但是空值是统计到其中。 79题 HEAP表是访问数据速度最快的MySQL表,他使用保存在内存中的散列索引。一旦服务器重启,所有heap表数据丢失。BLOB或TEXT字段是不允许的。只能使用比较运算符=,<,>,=>,= <。HEAP表不支持AUTO_INCREMENT。索引不可为NULL。 78题 如果想输入字符为十六进制数字,可以输入带有单引号的十六进制数字和前缀(X),或者只用(Ox)前缀输入十六进制数字。如果表达式上下文是字符串,则十六进制数字串将自动转换为字符串。 77题 Mysql服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。 76题 在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的。但是如果你的MYSQL表类型是使用InnoDB Tables 或 BDB tables的话,你的MYSQL就可以使用事务处理,使用SET AUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改。 75题 它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。 74题 创建索引的时候尽量使用唯一性大的列来创建索引,由于使用b+tree做为索引,以innodb为例,一个树节点的大小由“innodb_page_size”,为了减少树的高度,同时让一个节点能存放更多的值,索引列尽量在整数类型上创建,如果必须使用字符类型,也应该使用长度较少的字符类型。 73题 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下: 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读。垂直分区: 根据数据库里面数据表的相关性进行拆分。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。水平分区: 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。水平拆分可以支撑非常大的数据量。 72题 乐观锁失败后会抛出ObjectOptimisticLockingFailureException,那么我们就针对这块考虑一下重试,自定义一个注解,用于做切面。针对注解进行切面,设置最大重试次数n,然后超过n次后就不再重试。 71题 一致性非锁定读讲的是一条记录被加了X锁其他事务仍然可以读而不被阻塞,是通过innodb的行多版本实现的,行多版本并不是实际存储多个版本记录而是通过undo实现(undo日志用来记录数据修改前的版本,回滚时会用到,用来保证事务的原子性)。一致性锁定读讲的是我可以通过SELECT语句显式地给一条记录加X锁从而保证特定应用场景下的数据一致性。 70题 数据库引擎:尤其是mysql数据库只有是InnoDB引擎的时候事物才能生效。 show engines 查看数据库默认引擎;SHOW TABLE STATUS from 数据库名字 where Name='表名' 如下;SHOW TABLE STATUS from rrz where Name='rrz_cust';修改表的引擎alter table table_name engine=innodb。 69题 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);哈希索引也不支持多列联合索引的最左匹配规则;B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。 68题 decimal精度比float高,数据处理比float简单,一般优先考虑,但float存储的数据范围大,所以范围大的数据就只能用它了,但要注意一些处理细节,因为不精确可能会与自己想的不一致,也常有关于float 出错的问题。 67题 datetime、timestamp精确度都是秒,datetime与时区无关,存储的范围广(1001-9999),timestamp与时区有关,存储的范围小(1970-2038)。 66题 Char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。Varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储。char和varchar后面如果有空格,char会自动去掉空格后存储,varchar虽然不会去掉空格,但在进行字符串比较时,会去掉空格进行比较。Varbinary保存变长的字符串,后面不会补\0。 65题 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。 64题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 63题 存储过程是一些预编译的SQL语句。1、更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。 62题 密码散列、盐、用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率。 61题 推荐使用自增ID,不要使用UUID。因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。总之,在数据量大一些的情况下,用自增主键性能会好一些。 60题 char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间。在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。 59题 一. read uncommitted(读取未提交数据) 即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。 二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别 当前会话只能读取到其他事务提交的数据,未提交的数据读不到。 三. repeatable read(可重读)---MySQL默认的隔离级别 当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。 四. serializable(串行化) 其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。 58题 B+树的高度一般为2-4层,所以查找记录时最多只需要2-4次IO,相对二叉平衡树已经大大降低了。范围查找时,能通过叶子节点的指针获取数据。例如查找大于等于3的数据,当在叶子节点中查到3时,通过3的尾指针便能获取所有数据,而不需要再像二叉树一样再获取到3的父节点。 57题 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。 56题 redo log是物理日志,记录的是"在某个数据页上做了什么修改"。 binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给ID=2这一行的c字段加1"。 redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。 redo log是循环写的,空间固定会用完:binlog 是可以追加写入的。"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。 最开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog日志只能用于归档。而InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。 55题 重做日志(redo log)      作用:确保事务的持久性,防止在发生故障,脏页未写入磁盘。重启数据库会进行redo log执行重做,达到事务一致性。 回滚日志(undo log)  作用:保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。 二进 制日志(binlog)    作用:用于主从复制,实现主从同步;用于数据库的基于时间点的还原。 错误日志(errorlog) 作用:Mysql本身启动,停止,运行期间发生的错误信息。 慢查询日志(slow query log)  作用:记录执行时间过长的sql,时间阈值可以配置,只记录执行成功。 一般查询日志(general log)    作用:记录数据库的操作明细,默认关闭,开启后会降低数据库性能 。 中继日志(relay log) 作用:用于数据库主从同步,将主库发来的bin log保存在本地,然后从库进行回放。 54题 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。 那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。死锁的解决办法:1.查出的线程杀死。2.设置锁的超时时间。3.指定获取锁的顺序。 53题 当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性(脏读,不可重复读,幻读等),可能产生死锁。 乐观锁:乐观锁不是数据库自带的,需要我们自己去实现。 悲观锁:在进行每次操作时都要通过获取锁才能进行对相同数据的操作。 共享锁:加了共享锁的数据对象可以被其他事务读取,但不能修改。 排他锁:当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 行锁:就是给某一条记录加上锁。 52题 Mysql是关系型数据库,MongoDB是非关系型数据库,数据存储结构的不同。 51题 关系型数据库优点:1.保持数据的一致性(事务处理)。 2.由于以标准化为前提,数据更新的开销很小。 3. 可以进行Join等复杂查询。 缺点:1、为了维护一致性所付出的巨大代价就是其读写性能比较差。 2、固定的表结构。 3、高并发读写需求。 4、海量数据的高效率读写。 非关系型数据库优点:1、无需经过sql层的解析,读写性能很高。 2、基于键值对,数据没有耦合性,容易扩展。 3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。 缺点:1、不提供sql支持,学习和使用成本较高。 2、无事务处理,附加功能bi和报表等支持也不好。 redis与mongoDB的区别: 性能:TPS方面redis要大于mongodb。 可操作性:mongodb支持丰富的数据表达,索引,redis较少的网络IO次数。 可用性:MongoDB优于Redis。 一致性:redis事务支持比较弱,mongoDB不支持事务。 数据分析:mongoDB内置了数据分析的功能(mapreduce)。 应用场景:redis数据量较小的更性能操作和运算上,MongoDB主要解决海量数据的访问效率问题。 50题 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。 49题 分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。 48题 除了缓存服务器自带的缓存失效策略之外(Redis默认的有6种策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种: 1.定时去清理过期的缓存; 2.当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。 两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,可以根据应用场景来权衡。 47题 Redis提供了两种方式来作消息队列: 一个是使用生产者消费模式模式:会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列里没有消息,则消费者继续监听 。另一个就是发布订阅者模式:也是一个或多个客户端订阅消息频道,只要发布者发布消息,所有订阅者都能收到消息,订阅者都是平等的。 46题 Redis的数据结构列表(list)可以实现延时队列,可以通过队列和栈来实现。blpop/brpop来替换lpop/rpop,blpop/brpop阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。Redis的有序集合(zset)可以用于实现延时队列,消息作为value,时间作为score。Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。 45题 1.热点数据缓存:因为Redis 访问速度块、支持的数据类型比较丰富。 2.限时业务:expire 命令设置 key 的生存时间,到时间后自动删除 key。 3.计数器:incrby 命令可以实现原子性的递增。 4.排行榜:借助 SortedSet 进行热点数据的排序。 5.分布式锁:利用 Redis 的 setnx 命令进行。 6.队列机制:有 list push 和 list pop 这样的命令。 44题 一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。 43题 RDB的优点:适合做冷备份;读写服务影响小,reids可以保持高性能;重启和恢复redis进程,更加快速。RDB的缺点:宕机会丢失最近5分钟的数据;文件特别大时可能会暂停数毫秒,或者甚至数秒。 AOF的优点:每个一秒执行fsync操作,最多丢失1秒钟的数据;以append-only模式写入,没有任何磁盘寻址的开销;文件过大时,不会影响客户端读写;适合做灾难性的误删除的紧急恢复。AOF的缺点:AOF日志文件比RDB数据快照文件更大,支持写QPS比RDB支持的写QPS低;比RDB脆弱,容易有bug。 42题 对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。Redis的操作之所以是原子性的,是因为Redis是单线程的。而在程序中执行多个Redis命令并非是原子性的,这也和普通数据库的表现是一样的,可以用incr或者使用Redis的事务,或者使用Redis+Lua的方式实现。对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么执行失败,这就是Redis的命令是原子性的原因。 41题 (1)twemproxy,使用方式简单(相对redis只需修改连接端口),对旧项目扩展的首选。(2)codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在节点数改变情况下,旧节点数据可恢复到新hash节点。(3)redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。(4)在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key进行hash计算,然后去对应的redis实例操作数据。这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的代替算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。 40题 (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。 39题 比如订单管理,热数据:3个月内的订单数据,查询实时性较高;温数据:3个月 ~ 12个月前的订单数据,查询频率不高;冷数据:1年前的订单数据,几乎不会查询,只有偶尔的查询需求。热数据使用mysql进行存储,需要分库分表;温数据可以存储在ES中,利用搜索引擎的特性基本上也可以做到比较快的查询;冷数据可以存放到Hive中。从存储形式来说,一般情况冷数据存储在磁带、光盘,热数据一般存放在SSD中,存取速度快,而温数据可以存放在7200转的硬盘。 38题 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。 37题 分层架构设计,有一条准则:站点层、服务层要做到无数据无状态,这样才能任意的加节点水平扩展,数据和状态尽量存储到后端的数据存储服务,例如数据库服务或者缓存服务。显然进程内缓存违背了这一原则。 36题 更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。 35题 redis分布式锁加锁过程:通过setnx向特定的key写入一个随机值,并同时设置失效时间,写值成功既加锁成功;redis分布式锁解锁过程:匹配随机值,删除redis上的特点key数据,要保证获取数据、判断一致以及删除数据三个操作是原子的,为保证原子性一般使用lua脚本实现;在此基础上进一步优化的话,考虑使用心跳检测对锁的有效期进行续期,同时基于redis的发布订阅优雅的实现阻塞式加锁。 34题 volatile-lru:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。 volatile-ttl:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选将要过期的数据淘汰。 volatile-random:当内存不足以容纳写入数据时,从已设置过期时间的数据集中任意选择数据淘汰。 allkeys-lru:当内存不足以容纳写入数据时,从数据集中挑选最近最少使用的数据淘汰。 allkeys-random:当内存不足以容纳写入数据时,从数据集中任意选择数据淘汰。 noeviction:禁止驱逐数据,当内存使用达到阈值的时候,所有引起申请内存的命令会报错。 33题 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 32题 缓存击穿,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。如何避免:在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。 31题 缓存雪崩,是指在某一个时间段,缓存集中过期失效。大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。而缓存服务器某个节点宕机或断网,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。如何避免:1.redis高可用,搭建redis集群。2.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。3.数据预热,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间。 30题 缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。一些恶意的请求会故意查询不存在的 key,请求量很大,对数据库造成压力,甚至压垮数据库。 如何避免:1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。 29题 1.memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型。 2.redis 的速度比 memcached 快很多。 3.redis 可以持久化其数据。 4.Redis支持数据的备份,即master-slave模式的数据备份。 5.Redis采用VM机制。 6.value大小:redis最大可以达到1GB,而memcache只有1MB。 28题 Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过spring提供的@ImportResource来加载xml配置。例如:@ImportResource({"classpath:some-context.xml","classpath:another-context.xml"}) 27题 Spring像一个大家族,有众多衍生产品例如Spring Boot,Spring Security等等,但他们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,而AOP解决了面向切面的编程,然后在此两者的基础上实现了其他衍生产品的高级功能。Spring MVC是基于Servlet的一个MVC框架,主要解决WEB开发的问题,因为 Spring的配置非常复杂,各种xml,properties处理起来比较繁琐。Spring Boot遵循约定优于配置,极大降低了Spring使用门槛,又有着Spring原本灵活强大的功能。总结:Spring MVC和Spring Boot都属于Spring,Spring MVC是基于Spring的一个MVC框架,而Spring Boot是基于Spring的一套快速开发整合包。 26题 YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。YAML 的配置文件后缀为 .yml,是一种人类可读的数据序列化语言,可以简单表达清单、散列表,标量等数据形态。它通常用于配置文件,与属性文件相比,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 25题 Spring Boot有3种热部署方式: 1.使用springloaded配置pom.xml文件,使用mvn spring-boot:run启动。 2.使用springloaded本地加载启动,配置jvm参数-javaagent:<jar包地址> -noverify。 3.使用devtools工具包,操作简单,但是每次需要重新部署。 用

游客ih62co2qqq5ww 2020-03-27 23:56:48 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:27 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:28 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:28 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:28 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:27 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:28 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:28 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:27 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:28 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 本示例讲解如何在服务端通过PHP代码完成签名,然后通过表单直传数据到OSS。 说明 本示例无法实现分片上传与断点续传。 背景 采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)有一个严重的安全隐患:OSS AccessKey暴露在前端页面,这是非常不安全的做法。因此,OSS提供了服务端签名后直传的方案。 Demo 您可以通过样例体验服务端签名后直传效果:PC浏览器测试样例 原理介绍 服务端签名后直传的逻辑图如下: 流程如下: 用户发送上传Policy请求到应用服务器。 应用服务器返回上传Policy和签名给用户。 用户使用Plupload直接上传数据到OSS。 步骤 1:下载并安装Plugload Plupload是一款简单易用且功能强大的文件上传工具, 支持多种上传方式,包括html5、flash、silverlight,、html4。它会智能检测当前环境,选择最适合的上传方式,并且会优先采用Html5方式。请参见Plupload官网进行下载和安装。 步骤 2:下载应用服务器代码 PHP:下载地址 Java:下载地址 Python:下载地址 Go:下载地址 步骤 3:修改配置文件 本示例采用PHP编写。将下载包解压后,修改以下文件: php/get.php文件:$id= '<yourAccessKeyId>'; $key= '<yourAccessKeySecret>'; $host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com $id:您的AccessKeyId $key:您的AessKeySecret $host:格式为BucketName.Endpoint,例如post-test.oss-cn-hangzhou.aliyuncs.com 说明 关于Endpoint的介绍,请参见Endpoint(访问域名)。 upload.js文件 将变量severUrl改成服务器部署的地址,例如http://abc.com:8080/oss-h5-upload-js-php/get.php。 步骤 4:设置CORS HTML表单直接上传到OSS会产生跨域请求。为了浏览安全,需要为Bucket设置跨域规则(CORS),支持Post方法。 具体操作步骤请参见设置跨域访问。设置如下图所示: 说明 在低版本IE浏览器,Plupload会以Flash方式执行。您需要设置crossdomain.xml ,设置方法请参见OSS Web直传—使用Flash上传。 步骤 5:体验服务端签名后直传 将应用服务器代码zip包解压到Web根目录下。 在Web浏览器中输入<Web应用服务器地址>/oss-h5-upload-js-php/index.html,例如http://abc.com:8080/oss-h5-upload-js-php/index.html。 选择一个或多个文件进行上传。 上传成功后,通过控制台查看上传结果。 核心代码解析 设置成随机文件名 如果想在上传时固定设置成随机文件名,后缀保持跟客户端文件一致,可以将函数改为:function check_object_radio() { g_object_name_type = 'random_name'; } 设置成用户的文件名 如果想在上传时固定设置成用户的文件名,可以将函数改为:function check_object_radio() { g_object_name_type = 'local_name'; } 设置上传目录 上传的目录由服务端(即PHP)指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码是将上传目录改成abc/,注意目录必须以正斜线(/)结尾。$dir = 'abc/'; 设置上传过滤条件 您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。var uploader = new plupload.Uploader({ …… filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], max_file_size : '400kb', //最大只能上传400KB的文件 prevent_duplicates : true //不允许选取重复文件 }, mime_types:限制上传的文件后缀 max_file_size:限制上传的文件大小 prevent_duplicates:限制不能重复上传 说明 filters过滤条件不是必须的。如果不想设置过滤条件,只要把该项注释即可。 获取上传后的文件名 如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }可以利用如下函数,得到上传到OSS的文件名,其中file.name记录了上传本地文件的名称。get_uploaded_object_name(file.name) 上传签名 JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,获取这三个变量的核心代码如下:phpUrl = './php/get.php' xmlhttp.open( "GET", phpUrl, false ); xmlhttp.send( null ); var obj = eval ("(" + xmlhttp.responseText+ ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) key = obj['dir'] xmlhttp.responseText解析如下: 说明 以下仅为示例,并不要求必须是相同的格式,但是必须有accessid、policy、signature这三个值。 {"accessid":"6MKOqxGiGU4AUk44", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19", "signature":"I2u57FWjTKqX/AE6doIdyff151E=", "expire":1446726203,"dir":"user-dir/"} accessid:用户请求的accessid。 host:用户要往哪个域名发送上传请求。 policy:用户表单上传的策略(Policy),是经过base64编码过的字符串。 signature:对变量policy签名后的字符串。 expire:上传策略失效时间,在PolicyText里指定。在失效时间之前,都可以利用此Policy上传文件,所以没有必要每次上传都去服务端获取签名。 说明 为了减少服务端的压力,设计思路是:初始化上传时,每上传一个文件后,获取一次签名。然后再上传时,比较当前时间与签名时间,看签名时间是否失效。如果失效了,就重新获取一次签名,如果没有失效,就使用之前的签名。这里就用到了变量expire,核心代码如下:now = timestamp = Date.parse(new Date()) / 1000; [color=#000000]//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一次签名,缓冲时间为3[/color] if (expire < now + 3) {    .....    phpUrl = './php/get.php'    xmlhttp.open( "GET", phpUrl, false );    xmlhttp.send( null );    ...... } return . 解析Policy的内容如下:{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000], ["starts-with","$key","user-dir/"]] 说明 Policy的详细信息请参见Policy基本元素。 上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户可自行指定此字符串。增加starts-with的原因是:在很多场景下,一个应用对应一个Bucket,为了防止数字覆盖,每个用户上传到OSS的文件都可以有特定的前缀。这样就存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到别人的目录下。为了解决这个问题,可以设置应用服务器在上传时就指定用户上传的文件必须是某个前缀。这样如果用户获取到了Policy也没有办法上传到别人的前缀上,从而保证了数据的安全性。 总结 本示例中,web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。但是这个示例有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能马上知道,如果想实时了解用户上传了什么文件,可以采用服务端签名直传并设置上传回调。

2019-12-01 23:13:27 0 浏览量 回答数 0

回答

PHP面试干货 1、进程和线程 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于: 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 2、apache默认使用进程管理还是线程管理?如何判断并设置最大连接数? 一个进程可以开多个线程 默认是进程管理 默认有一个主进程 Linux: ps -aux | grep httpd | more 一个子进程代表一个用户的连接 Conf/extra/httpd-mpm.conf 多路功能模块 http -l 查询当前apache处于什么模式下 3、单例模式 单例模式需求:只能实例化产生一个对象 如何实现: 私有化构造函数 禁止克隆对象 提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一对象 需要一个保存类的静态属性 class demo { private static $MyObject; //保存对象的静态属性 private function __construct(){ //私有化构造函数 } private function __clone(){ //禁止克隆 } public static function getInstance(){ if(! (self::$MyObject instanceof self)){ self::$MyObject = new self; } return self::$MyObject; } } 4、安装完Apache后,在http.conf中配置加载PHP文件以Apache模块的方式安装PHP,在文件http.conf中首先要用语句LoadModule php5_module "e:/php/php5apache2.dll"动态装载PHP模块,然后再用语句AddType application/x-httpd-php .php 使得Apache把所有扩展名为PHP的文件都作为PHP脚本处理 5、debug_backtrace()函数能返回脚本里的任意行中调用的函数的名称。该函数同时还经常被用在调试中,用来判断错误是如何发生的 function one($str1, $str2) { two("Glenn", "Quagmire"); } function two($str1, $str2) { three("Cleveland", "Brown"); } function three($str1, $str2) { print_r(debug_backtrace()); } one("Peter", "Griffin"); Array ( [0] => Array ( [file] => D:\www\test\result.php [line] => 9 [function] => three [args] => Array ( [0] => Cleveland [1] => Brown ) ) [1] => Array ( [file] => D:\www\test\result.php [line] => 5 [function] => two [args] => Array ( [0] => Glenn [1] => Quagmire ) ) [2] => Array ( [file] => D:\www\test\result.php [line] => 16 [function] => one [args] => Array ( [0] => Peter [1] => Griffin ) ) ) 6、输出用户的IP地址,并且判断用户的IP地址是否在192.168.1.100 — 192.168.1.150之间 echo $ip=getenv('REMOTE_ADDR'); $ip=str_replace('.','',$ip); if($ip<1921681150 && $ip>1921681100) { echo 'ip在192.168.1.100—–192.168.1.150之间'; } else { echo 'ip不在192.168.1.100—–192.168.1.150之间'; } 7、请将2维数组按照name的长度进行重新排序,按照顺序将id赋值 $tarray = array( array('id' => 0, 'name' => '123'), array('id' => 0, 'name' => '1234'), array('id' => 0, 'name' => '1235'), array('id' => 0, 'name' => '12356'), array('id' => 0, 'name' => '123abc') ); foreach($tarray as $key=>$val) { $c[]=$val['name']; } function aa($a,$b) { if(strlen($a)==strlen($b)) return 0; return strlen($a)>strlen($b)?-1:1; } usort($c,'aa'); $len=count($c); for($i=0;$i<$len;$i++) { $t[$i]['id']=$i+1; $t[$i]['name']=$c[$i]; } print_r($t); 8、表单数据提交方式POST和GET的区别,URL地址传递的数据最大长度是多少? POST方式提交数据用户不可见,是数据更安全,最大长度不受限制,而GET方式传值在URL地址可以看到,相对不安全,对大长度是2048字节。 9、SESSION和COOKIE的作用和区别,SESSION信息的存储方式,如何进行遍历 SESSION和COOKIE都能够使值在页面之间进行传递,SESSION存储在服务器端,数据更安全,COOKIE保存在客户端,用户使用手段可以进行修改,SESSION依赖于COOKIE进行传递的。Session遍历使用$_SESSION[]取值,cookie遍历使用$_COOKIE[]取值。 10、什么是数据库索引,主键索引,唯一索引的区别,索引的缺点是什么 索引用来快速地寻找那些具有特定值的记录。 主键索引和唯一索引的区别:主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”,每个表只能有一个主键。唯一索引索引列的所有值都只能出现一次,即必须唯一。 索引的缺点: 1、创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 2、索引需要占用物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,需要的空间就会更大。 3、当对表中的数据进行增加、删除、修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 11、数据库设计时,常遇到的性能瓶颈有哪些,常有的解决方案 瓶颈主要有: 1、磁盘搜索 优化方法是:将数据分布在多个磁盘上 2、磁盘读/写 优化方法是:从多个磁盘并行读写。 3、CPU周期 优化方法:扩充内存 4、内存带宽 12、include和require区别 include引入文件的时候,如果碰到错误,会给出提示,并继续运行下边的代码。 require引入文件的时候,如果碰到错误,会给出提示,并停止运行下边的代码。 13、文件上传时设计到点 和文件上传有关的php.ini配置选项(File Uploads): file_uploads=On/Off:文件是否允许上传 upload_max_filesize上传文件时,单个文件的最大大小 post_max_size:提交表单时,整个post表单的最大大小 max_file_uploads =20上传文件的个数 内存占用,脚本最大执行时间也间接影响到文件的上传 14、header常见状态 //200 正常状态 header('HTTP/1.1 200 OK'); // 301 永久重定向,记得在后面要加重定向地址 Location:$url header('HTTP/1.1 301 Moved Permanently'); // 重定向,其实就是302 暂时重定向 header('Location: http://www.maiyoule.com/'); // 设置页面304 没有修改 header('HTTP/1.1 304 Not Modified'); // 显示登录框, header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Basic realm="登录信息"'); echo '显示的信息!'; // 403 禁止访问 header('HTTP/1.1 403 Forbidden'); // 404 错误 header('HTTP/1.1 404 Not Found'); // 500 服务器错误 header('HTTP/1.1 500 Internal Server Error'); // 3秒后重定向指定地址(也就是刷新到新页面与 <meta http-equiv="refresh" content="10;http://www.maiyoule.com/ /> 相同) header('Refresh: 3; url=http://www.maiyoule.com/'); echo '10后跳转到http://www.maiyoule.com'; // 重写 X-Powered-By 值 header('X-Powered-By: PHP/5.3.0'); header('X-Powered-By: Brain/0.6b'); //设置上下文语言 header('Content-language: en'); // 设置页面最后修改时间(多用于防缓存) $time = time() - 60; //建议使用filetime函数来设置页面缓存时间 header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); // 设置内容长度 header('Content-Length: 39344'); // 设置头文件类型,可以用于流文件或者文件下载 header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="example.zip"'); header('Content-Transfer-Encoding: binary'); readfile('example.zip');//读取文件到客户端 //禁用页面缓存 header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Pragma: no-cache'); //设置页面头信息 header('Content-Type: text/html; charset=iso-8859-1'); header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/plain'); header('Content-Type: image/jpeg'); header('Content-Type: application/zip'); header('Content-Type: application/pdf'); header('Content-Type: audio/mpeg'); header('Content-Type: application/x-shockwave-flash'); //.... 至于Content-Type 的值 可以去查查 w3c 的文档库,那里很丰富 15、ORM和ActiveRecord ORM:object relation mapping,即对象关系映射,简单的说就是对象模型和关系模型的一种映射。为什么要有这么一个映射?很简单,因为现在的开发语言基本都是oop的,但是传统的数据库却是关系型的。为了可以靠贴近面向对象开发,我们想要像操作对象一样操作数据库。还可以隔离底层数据库层,我们不需要关心我们使用的是mysql还是其他的关系型数据库 ActiveRecord也属于ORM层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。 ActiveRecord的主要思想是: 1. 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field; 2. ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;; 3. ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑; ActiveRecord比较适用于: 1. 业务逻辑比较简单,当你的类基本上和数据库中的表一一对应时, ActiveRecord是非常方便的,即你的业务逻辑大多数是对单表操作; 2. 当发生跨表的操作时, 往往会配合使用事务脚本(Transaction Script),把跨表事务提升到事务脚本中; 3. ActiveRecord最大优点是简单, 直观。 一个类就包括了数据访问和业务逻辑. 如果配合代码生成器使用就更方便了; 这些优点使ActiveRecord特别适合WEB快速开发。 16、斐波那契方法,也就是1 1 2 3 5 8 ……,这里给出两种方法,大家可以对比下,看看哪种快,以及为什么 function fibonacci($n){ if($n == 0){ return 0; } if($n == 1){ return 1; } return fibonacci($n-1)+fibonacci($n-2); } function fibonacci($n){ for($i=0; $i<$n; $i++){ $r[] = $i<2 ? 1 : $r[$i-1]+$r[$i-2]; } return $r[--$i]; } 17、约瑟夫环,也就是常见的数猴子,n只猴子围成一圈,每只猴子下面标了编号,从1开始数起,数到m那么第m只猴子便退出,依次类推,每数到m,那么那个位置的猴子退出,那么最后剩下的猴子下的编号是啥。 function yuesefu($n,$m) { $r=0; for($i=2; $i<=$n; $i++) { $r=($r+$m)%$i; } return $r+1; } 18、冒泡排序,大致是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束 function bubbleSort($arr){ for($i=0, $len=count($arr); $i<$len; $i++){ for($j=0; $j<$len; $j++){ if($arr[$i]<$arr[$j]){ $tmp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $tmp; } } } return $arr; } 19、快速排序,也就是找出一个元素(理论上可以随便找一个)作为基准,然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。 function quickSort($arr){ $len = count($arr); if($len <=1){ return $arr; } $key = $arr[0]; $leftArr = $rightArr= array(); for($i=1; $i<$len; $i++){ if($arr[$i] <= $key){ $leftArr[] = $arr[$i]; } else{ $rightArr[] = $arr[$i]; } } $leftArr = quickSort($leftArr); $rightArr = quickSort($rightArr); return array_merge($leftArr, array($key), $rightArr); } 20、(递归的)列出目录下所有文件及目录,这里也有两种方法 function listDir($path){ $res = dir($path); while($file = $res->read()){ if($file == '.' || $file == '..'){ continue; } if(is_dir($path . '/' .$file)){ echo $path . '/' .$file . "\r\n"; listDir($path . '/' .$file); } else{ echo $path . '/' .$file . "\r\n"; } } $res->close(); } function listDir($path){ if(is_dir($path)){ if(FALSE !== ($res = opendir($path))){ while(FALSE !== ($file = readdir($res))){ if($file == '.' || $file == '..'){ continue; } $subPath = $path . '/' . $file; if(is_dir($subPath)){ echo $subPath . "\r\n"; listDir($subPath); } else{ echo $subPath . "\r\n"; } } } } } 21、找出相对的目录,比如/a/b/c/d/e.php相对于/a/b/13/34/c.php是/c/d/ function ralativePath($a, $b){ $a = explode('/', dirname($a)); $b = explode('/', dirname($b)); $c = '/'; foreach ($a as $k=> $v){ if($v != $b[$k]){ $c .= $v . '/'; } } echo $c; } 22、快速找出url中php后缀 function get_ext($url){ $data = parse_url($url); return pathinfo($data['path'], PATHINFO_EXTENSION); } 23、正则题,使用正则抓取网页,以网页meta为utf8为准,若是抓取的网页编码为big5之类的,需要转化为utf8再收录 function preg_meta($meta){ $replacement = "\\1utf8\\6\\7"; $pattern = '#(<meta\s+http-equiv=(\'|"|)Content-Type(\'|"|)\s+content=(\'|"|)text/html; charset=)(\w+)(\'|"|)(>)#i'; return preg_replace($pattern, $replacement, $meta); } echo preg_meta("<meta http-equiv=Content-Type content='text/html; charset=big5'><META http-equiv=\"Content-Type\" content='text/html; charset=big5'>"); 24、不用php的反转函数倒序输出字符串,如abc,反序输出cba function revstring($str){ for($i=strlen($str)-1; $i>=0; $i--){ echo $str{$i}; } } revstring('abc'); 25、常见端口 TCP 21端口:FTP 文件传输服务 SSH 22端口:SSH连接linux服务器,通过SSH连接可以远程管理Linux等设备 TCP 23端口:TELNET 终端仿真服务 TCP 25端口:SMTP 简单邮件传输服务 UDP 53端口:DNS 域名解析服务 TCP 80端口:HTTP 超文本传输服务 TCP 110端口:POP3 “邮局协议版本3”使用的端口 TCP 443端口:HTTPS 加密的超文本传输服务 TCP 1521端口:Oracle数据库服务 TCP 1863端口:MSN Messenger的文件传输功能所使用的端口 TCP 3389端口:Microsoft RDP 微软远程桌面使用的端口 TCP 5631端口:Symantec pcAnywhere 远程控制数据传输时使用的端口 UDP 5632端口:Symantec pcAnywhere 主控端扫描被控端时使用的端口 TCP 5000端口:MS SQL Server使用的端口 UDP 8000端口:腾讯QQ 26、linux常用的命令 top linux进程实时监控 ps 在Linux中是查看进程的命令。ps查看正处于Running的进程 mv 为文件或目录改名或将文件由一个目录移入另一个目录中。 find 查找文件 df 可显示所有文件系统对i节点和磁盘块的使用情况。 cat 打印文件类容 chmod 变更文件或目录的权限 chgrp 文件或目录的权限的掌控以拥有者及所诉群组来管理。可以使用chgrp指令取变更文件与目录所属群组 grep 是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。 wc 为统计指定文件中的字节数、字数、行数,并将统计结果显示输出 27、对于大流量的网站,您采用什么样的方法来解决访问量问题 首先,确认服务器硬件是否足够支持当前的流量 其次,优化数据库访问。 第三,禁止外部的盗链。 第四,控制大文件的下载。 第五,使用不同主机分流主要流量 第六,使用流量分析统计软件 28、$_SERVER常用的字段 $_SERVER['PHP_SELF'] #当前正在执行脚本的文件名 $_SERVER['SERVER_NAME'] #当前运行脚本所在服务器主机的名称 $_SERVER['REQUEST_METHOD'] #访问页面时的请求方法。例如:“GET”、“HEAD”,“POST”,“PUT” $_SERVER['QUERY_STRING'] #查询(query)的字符串 $_SERVER['HTTP_HOST'] #当前请求的 Host: 头部的内容 $_SERVER['HTTP_REFERER'] #链接到当前页面的前一页面的 URL 地址 $_SERVER['REMOTE_ADDR'] #正在浏览当前页面用户的 IP 地址 $_SERVER['REMOTE_HOST'] #正在浏览当前页面用户的主机名 $_SERVER['SCRIPT_FILENAME'] #当前执行脚本的绝对路径名 $_SERVER['SCRIPT_NAME'] #包含当前脚本的路径。这在页面需要指向自己时非常有用 $_SERVER['REQUEST_URI'] #访问此页面所需的 URI。例如,“/index.html” 29、安装php扩展 进入扩展的目录 phpize命令得到configure文件 ./configure --with-php-config=/usr/local/php/bin/php-config make & make install 在php.ini中加入扩展名称.so 重启web服务器(nginx/apache) 30、php-fpm与nginx PHP-FPM也是一个第三方的FastCGI进程管理器,它是作为PHP的一个补丁来开发的,在安装的时候也需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此在处理性能方面更加优秀;同时它在处理高并发方面也比spawn-fcgi引擎好很多,因此,推荐Nginx+PHP/PHP-FPM这个组合对PHP进行解析。 FastCGI 的主要优点是把动态语言和HTTP Server分离开来,所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上,以分担前端Nginx服务器的压力,使Nginx专一处理静态请求和转发动态请求,而PHP/PHP-FPM服务器专一解析PHP动态请求 #fastcgi FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP。 FastCGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后结果被返回给HTTP服务器。这在处理高并发访问时,几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在已经很少被使用了。 FastCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。 Nginx+FastCGI运行原理 Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket,(这个socket可以是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接纳到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端,这就是Nginx+FastCGI的整个运作过程。 31、ajax全称“Asynchronous Javascript And XML”(异步JavaScript和XML)

小川游鱼 2019-12-02 01:41:29 0 浏览量 回答数 0

回答

PHP面试干货 1、进程和线程 进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于: 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高。 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。 2、apache默认使用进程管理还是线程管理?如何判断并设置最大连接数? 一个进程可以开多个线程 默认是进程管理 默认有一个主进程 Linux: ps -aux | grep httpd | more 一个子进程代表一个用户的连接 Conf/extra/httpd-mpm.conf 多路功能模块 http -l 查询当前apache处于什么模式下 3、单例模式 单例模式需求:只能实例化产生一个对象 如何实现: 私有化构造函数 禁止克隆对象 提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一对象 需要一个保存类的静态属性 class demo { private static $MyObject; //保存对象的静态属性 private function __construct(){ //私有化构造函数 } private function __clone(){ //禁止克隆 } public static function getInstance(){ if(! (self::$MyObject instanceof self)){ self::$MyObject = new self; } return self::$MyObject; } } 4、安装完Apache后,在http.conf中配置加载PHP文件以Apache模块的方式安装PHP,在文件http.conf中首先要用语句LoadModule php5_module "e:/php/php5apache2.dll"动态装载PHP模块,然后再用语句AddType application/x-httpd-php .php 使得Apache把所有扩展名为PHP的文件都作为PHP脚本处理 5、debug_backtrace()函数能返回脚本里的任意行中调用的函数的名称。该函数同时还经常被用在调试中,用来判断错误是如何发生的 function one($str1, $str2) { two("Glenn", "Quagmire"); } function two($str1, $str2) { three("Cleveland", "Brown"); } function three($str1, $str2) { print_r(debug_backtrace()); } one("Peter", "Griffin"); Array ( [0] => Array ( [file] => D:\www\test\result.php [line] => 9 [function] => three [args] => Array ( [0] => Cleveland [1] => Brown ) ) [1] => Array ( [file] => D:\www\test\result.php [line] => 5 [function] => two [args] => Array ( [0] => Glenn [1] => Quagmire ) ) [2] => Array ( [file] => D:\www\test\result.php [line] => 16 [function] => one [args] => Array ( [0] => Peter [1] => Griffin ) ) ) 6、输出用户的IP地址,并且判断用户的IP地址是否在192.168.1.100 — 192.168.1.150之间 echo $ip=getenv('REMOTE_ADDR'); $ip=str_replace('.','',$ip); if($ip<1921681150 && $ip>1921681100) { echo 'ip在192.168.1.100—–192.168.1.150之间'; } else { echo 'ip不在192.168.1.100—–192.168.1.150之间'; } 7、请将2维数组按照name的长度进行重新排序,按照顺序将id赋值 $tarray = array( array('id' => 0, 'name' => '123'), array('id' => 0, 'name' => '1234'), array('id' => 0, 'name' => '1235'), array('id' => 0, 'name' => '12356'), array('id' => 0, 'name' => '123abc') ); foreach($tarray as $key=>$val) { $c[]=$val['name']; } function aa($a,$b) { if(strlen($a)==strlen($b)) return 0; return strlen($a)>strlen($b)?-1:1; } usort($c,'aa'); $len=count($c); for($i=0;$i<$len;$i++) { $t[$i]['id']=$i+1; $t[$i]['name']=$c[$i]; } print_r($t); 8、表单数据提交方式POST和GET的区别,URL地址传递的数据最大长度是多少? POST方式提交数据用户不可见,是数据更安全,最大长度不受限制,而GET方式传值在URL地址可以看到,相对不安全,对大长度是2048字节。 9、SESSION和COOKIE的作用和区别,SESSION信息的存储方式,如何进行遍历 SESSION和COOKIE都能够使值在页面之间进行传递,SESSION存储在服务器端,数据更安全,COOKIE保存在客户端,用户使用手段可以进行修改,SESSION依赖于COOKIE进行传递的。Session遍历使用$_SESSION[]取值,cookie遍历使用$_COOKIE[]取值。 10、什么是数据库索引,主键索引,唯一索引的区别,索引的缺点是什么 索引用来快速地寻找那些具有特定值的记录。 主键索引和唯一索引的区别:主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”,每个表只能有一个主键。唯一索引索引列的所有值都只能出现一次,即必须唯一。 索引的缺点: 1、创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 2、索引需要占用物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,需要的空间就会更大。 3、当对表中的数据进行增加、删除、修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 11、数据库设计时,常遇到的性能瓶颈有哪些,常有的解决方案 瓶颈主要有: 1、磁盘搜索 优化方法是:将数据分布在多个磁盘上 2、磁盘读/写 优化方法是:从多个磁盘并行读写。 3、CPU周期 优化方法:扩充内存 4、内存带宽 12、include和require区别 include引入文件的时候,如果碰到错误,会给出提示,并继续运行下边的代码。 require引入文件的时候,如果碰到错误,会给出提示,并停止运行下边的代码。 13、文件上传时设计到点 和文件上传有关的php.ini配置选项(File Uploads): file_uploads=On/Off:文件是否允许上传 upload_max_filesize上传文件时,单个文件的最大大小 post_max_size:提交表单时,整个post表单的最大大小 max_file_uploads =20上传文件的个数 内存占用,脚本最大执行时间也间接影响到文件的上传 14、header常见状态 //200 正常状态 header('HTTP/1.1 200 OK'); // 301 永久重定向,记得在后面要加重定向地址 Location:$url header('HTTP/1.1 301 Moved Permanently'); // 重定向,其实就是302 暂时重定向 header('Location: http://www.maiyoule.com/'); // 设置页面304 没有修改 header('HTTP/1.1 304 Not Modified'); // 显示登录框, header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Basic realm="登录信息"'); echo '显示的信息!'; // 403 禁止访问 header('HTTP/1.1 403 Forbidden'); // 404 错误 header('HTTP/1.1 404 Not Found'); // 500 服务器错误 header('HTTP/1.1 500 Internal Server Error'); // 3秒后重定向指定地址(也就是刷新到新页面与 <meta http-equiv="refresh" content="10;http://www.maiyoule.com/ /> 相同) header('Refresh: 3; url=http://www.maiyoule.com/'); echo '10后跳转到http://www.maiyoule.com'; // 重写 X-Powered-By 值 header('X-Powered-By: PHP/5.3.0'); header('X-Powered-By: Brain/0.6b'); //设置上下文语言 header('Content-language: en'); // 设置页面最后修改时间(多用于防缓存) $time = time() - 60; //建议使用filetime函数来设置页面缓存时间 header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); // 设置内容长度 header('Content-Length: 39344'); // 设置头文件类型,可以用于流文件或者文件下载 header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="example.zip"'); header('Content-Transfer-Encoding: binary'); readfile('example.zip');//读取文件到客户端 //禁用页面缓存 header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Pragma: no-cache'); //设置页面头信息 header('Content-Type: text/html; charset=iso-8859-1'); header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/plain'); header('Content-Type: image/jpeg'); header('Content-Type: application/zip'); header('Content-Type: application/pdf'); header('Content-Type: audio/mpeg'); header('Content-Type: application/x-shockwave-flash'); //.... 至于Content-Type 的值 可以去查查 w3c 的文档库,那里很丰富 15、ORM和ActiveRecord ORM:object relation mapping,即对象关系映射,简单的说就是对象模型和关系模型的一种映射。为什么要有这么一个映射?很简单,因为现在的开发语言基本都是oop的,但是传统的数据库却是关系型的。为了可以靠贴近面向对象开发,我们想要像操作对象一样操作数据库。还可以隔离底层数据库层,我们不需要关心我们使用的是mysql还是其他的关系型数据库 ActiveRecord也属于ORM层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。 ActiveRecord的主要思想是: 1. 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field; 2. ActiveRecord同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;; 3. ActiveRecord是一种领域模型(Domain Model),封装了部分业务逻辑; ActiveRecord比较适用于: 1. 业务逻辑比较简单,当你的类基本上和数据库中的表一一对应时, ActiveRecord是非常方便的,即你的业务逻辑大多数是对单表操作; 2. 当发生跨表的操作时, 往往会配合使用事务脚本(Transaction Script),把跨表事务提升到事务脚本中; 3. ActiveRecord最大优点是简单, 直观。 一个类就包括了数据访问和业务逻辑. 如果配合代码生成器使用就更方便了; 这些优点使ActiveRecord特别适合WEB快速开发。 16、斐波那契方法,也就是1 1 2 3 5 8 ……,这里给出两种方法,大家可以对比下,看看哪种快,以及为什么 function fibonacci($n){ if($n == 0){ return 0; } if($n == 1){ return 1; } return fibonacci($n-1)+fibonacci($n-2); } function fibonacci($n){ for($i=0; $i<$n; $i++){ $r[] = $i<2 ? 1 : $r[$i-1]+$r[$i-2]; } return $r[--$i]; } 17、约瑟夫环,也就是常见的数猴子,n只猴子围成一圈,每只猴子下面标了编号,从1开始数起,数到m那么第m只猴子便退出,依次类推,每数到m,那么那个位置的猴子退出,那么最后剩下的猴子下的编号是啥。 function yuesefu($n,$m) { $r=0; for($i=2; $i<=$n; $i++) { $r=($r+$m)%$i; } return $r+1; } 18、冒泡排序,大致是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束 function bubbleSort($arr){ for($i=0, $len=count($arr); $i<$len; $i++){ for($j=0; $j<$len; $j++){ if($arr[$i]<$arr[$j]){ $tmp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $tmp; } } } return $arr; } 19、快速排序,也就是找出一个元素(理论上可以随便找一个)作为基准,然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正 确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。 function quickSort($arr){ $len = count($arr); if($len <=1){ return $arr; } $key = $arr[0]; $leftArr = $rightArr= array(); for($i=1; $i<$len; $i++){ if($arr[$i] <= $key){ $leftArr[] = $arr[$i]; } else{ $rightArr[] = $arr[$i]; } } $leftArr = quickSort($leftArr); $rightArr = quickSort($rightArr); return array_merge($leftArr, array($key), $rightArr); } 20、(递归的)列出目录下所有文件及目录,这里也有两种方法 function listDir($path){ $res = dir($path); while($file = $res->read()){ if($file == '.' || $file == '..'){ continue; } if(is_dir($path . '/' .$file)){ echo $path . '/' .$file . "\r\n"; listDir($path . '/' .$file); } else{ echo $path . '/' .$file . "\r\n"; } } $res->close(); } function listDir($path){ if(is_dir($path)){ if(FALSE !== ($res = opendir($path))){ while(FALSE !== ($file = readdir($res))){ if($file == '.' || $file == '..'){ continue; } $subPath = $path . '/' . $file; if(is_dir($subPath)){ echo $subPath . "\r\n"; listDir($subPath); } else{ echo $subPath . "\r\n"; } } } } } 21、找出相对的目录,比如/a/b/c/d/e.php相对于/a/b/13/34/c.php是/c/d/ function ralativePath($a, $b){ $a = explode('/', dirname($a)); $b = explode('/', dirname($b)); $c = '/'; foreach ($a as $k=> $v){ if($v != $b[$k]){ $c .= $v . '/'; } } echo $c; } 22、快速找出url中php后缀 function get_ext($url){ $data = parse_url($url); return pathinfo($data['path'], PATHINFO_EXTENSION); } 23、正则题,使用正则抓取网页,以网页meta为utf8为准,若是抓取的网页编码为big5之类的,需要转化为utf8再收录 function preg_meta($meta){ $replacement = "\\1utf8\\6\\7"; $pattern = '#(<meta\s+http-equiv=(\'|"|)Content-Type(\'|"|)\s+content=(\'|"|)text/html; charset=)(\w+)(\'|"|)(>)#i'; return preg_replace($pattern, $replacement, $meta); } echo preg_meta("<meta http-equiv=Content-Type content='text/html; charset=big5'><META http-equiv=\"Content-Type\" content='text/html; charset=big5'>"); 24、不用php的反转函数倒序输出字符串,如abc,反序输出cba function revstring($str){ for($i=strlen($str)-1; $i>=0; $i--){ echo $str{$i}; } } revstring('abc'); 25、常见端口 TCP 21端口:FTP 文件传输服务 SSH 22端口:SSH连接linux服务器,通过SSH连接可以远程管理Linux等设备 TCP 23端口:TELNET 终端仿真服务 TCP 25端口:SMTP 简单邮件传输服务 UDP 53端口:DNS 域名解析服务 TCP 80端口:HTTP 超文本传输服务 TCP 110端口:POP3 “邮局协议版本3”使用的端口 TCP 443端口:HTTPS 加密的超文本传输服务 TCP 1521端口:Oracle数据库服务 TCP 1863端口:MSN Messenger的文件传输功能所使用的端口 TCP 3389端口:Microsoft RDP 微软远程桌面使用的端口 TCP 5631端口:Symantec pcAnywhere 远程控制数据传输时使用的端口 UDP 5632端口:Symantec pcAnywhere 主控端扫描被控端时使用的端口 TCP 5000端口:MS SQL Server使用的端口 UDP 8000端口:腾讯QQ 26、linux常用的命令 top linux进程实时监控 ps 在Linux中是查看进程的命令。ps查看正处于Running的进程 mv 为文件或目录改名或将文件由一个目录移入另一个目录中。 find 查找文件 df 可显示所有文件系统对i节点和磁盘块的使用情况。 cat 打印文件类容 chmod 变更文件或目录的权限 chgrp 文件或目录的权限的掌控以拥有者及所诉群组来管理。可以使用chgrp指令取变更文件与目录所属群组 grep 是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。 wc 为统计指定文件中的字节数、字数、行数,并将统计结果显示输出 27、对于大流量的网站,您采用什么样的方法来解决访问量问题 首先,确认服务器硬件是否足够支持当前的流量 其次,优化数据库访问。 第三,禁止外部的盗链。 第四,控制大文件的下载。 第五,使用不同主机分流主要流量 第六,使用流量分析统计软件 28、$_SERVER常用的字段 $_SERVER['PHP_SELF'] #当前正在执行脚本的文件名 $_SERVER['SERVER_NAME'] #当前运行脚本所在服务器主机的名称 $_SERVER['REQUEST_METHOD'] #访问页面时的请求方法。例如:“GET”、“HEAD”,“POST”,“PUT” $_SERVER['QUERY_STRING'] #查询(query)的字符串 $_SERVER['HTTP_HOST'] #当前请求的 Host: 头部的内容 $_SERVER['HTTP_REFERER'] #链接到当前页面的前一页面的 URL 地址 $_SERVER['REMOTE_ADDR'] #正在浏览当前页面用户的 IP 地址 $_SERVER['REMOTE_HOST'] #正在浏览当前页面用户的主机名 $_SERVER['SCRIPT_FILENAME'] #当前执行脚本的绝对路径名 $_SERVER['SCRIPT_NAME'] #包含当前脚本的路径。这在页面需要指向自己时非常有用 $_SERVER['REQUEST_URI'] #访问此页面所需的 URI。例如,“/index.html” 29、安装php扩展 进入扩展的目录 phpize命令得到configure文件 ./configure --with-php-config=/usr/local/php/bin/php-config make & make install 在php.ini中加入扩展名称.so 重启web服务器(nginx/apache) 30、php-fpm与nginx PHP-FPM也是一个第三方的FastCGI进程管理器,它是作为PHP的一个补丁来开发的,在安装的时候也需要和PHP源码一起编译,也就是说PHP-FPM被编译到PHP内核中,因此在处理性能方面更加优秀;同时它在处理高并发方面也比spawn-fcgi引擎好很多,因此,推荐Nginx+PHP/PHP-FPM这个组合对PHP进行解析。 FastCGI 的主要优点是把动态语言和HTTP Server分离开来,所以Nginx与PHP/PHP-FPM经常被部署在不同的服务器上,以分担前端Nginx服务器的压力,使Nginx专一处理静态请求和转发动态请求,而PHP/PHP-FPM服务器专一解析PHP动态请求 #fastcgi FastCGI是一个可伸缩地、高速地在HTTP server和动态脚本语言间通信的接口。多数流行的HTTP server都支持FastCGI,包括Apache、Nginx和lighttpd等,同时,FastCGI也被许多脚本语言所支持,其中就有PHP。 FastCGI是从CGI发展改进而来的。传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后结果被返回给HTTP服务器。这在处理高并发访问时,几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在已经很少被使用了。 FastCGI接口方式采用C/S结构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。 Nginx+FastCGI运行原理 Nginx不支持对外部程序的直接调用或者解析,所有的外部程序(包括PHP)必须通过FastCGI接口来调用。FastCGI接口在Linux下是socket,(这个socket可以是文件socket,也可以是ip socket)。为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接纳到请求,然后派生出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据发送给客户端,这就是Nginx+FastCGI的整个运作过程。 31、ajax全称“Asynchronous Javascript And XML”(异步JavaScript和XML)

小川游鱼 2019-12-02 01:41:29 0 浏览量 回答数 0

回答

不良的编程习惯TOP1:粘贴复制 在学生时代,我们都知道抄袭是不对的。但在工作中,这方面的规则还很模糊。虽然有些代码块是不能盗用的——不要把专有代码拷贝到你的堆栈中,尤其是这些代码有标记版权信息。这种时候你应该编写自己的版本,老板付你薪水就是要做正事的。 但是当原始创作者想要共享代码时,问题就变得复杂了。这些共享代码也许放到了某个在线编程论坛上,也许它们是带有许可证(BSD,MIT)的开放源代码,允许使用一到三个函数。你使用这些共享代码是没有问题的,而且你上班是为了解决问题,而不是重新发明轮子。 大多数情况下,复制代码的优势非常明显,小心对待的话问题也不大。至少那些从靠谱的来源获得的代码已经被大致“检查“过了。 问题的复杂之处在于,这些共享代码是否存在一些未发现的错误,代码的用途或底层数据是否存在一些特别的假设。也许你的代码混入了空指针,而原始代码从未检查过。如果你能解决这些问题,那么就可以理解为你的老板得到了两位程序员共同努力的成果。这就是某种形式的结对编程,而且用不着什么高大上的办公桌。 不良的编程习惯TOP2:非函数式代码 在过去十年间,函数范式愈加流行。喜欢用嵌套函数调用来构建程序的人们引用了很多研究成果。这些研究表明,与旧式的变量和循环相比,函数式编程代码更安全,错误更少,而且可以随程序员的喜好任意组合在一起。粉丝们十分追捧函数式编程,还会在代码审查和拉取请求中诋毁非函数式方法。关于这种方法的优势,他们的观点其实并没有错。 但有时你需要的仅仅是一卷胶带而已。精心设计并细心计划的代码需要花费很多时间,不仅需要花费时间想象,还需要构建和之后导航的时间。这些都增加了复杂性,并且会花费很多的时间与精力。开发漂亮的函数式代码需要提前做计划,还要确保所有数据都通过正确的途径传递。有时找出并更改变量会简单得多,可能再加个注释说明一下就够了。就算要在注释中为之后的程序员致以冗长而难懂的歉意,也比重新设计整个系统,把它扳回正轨上要省事得多。 不良的编程习惯第 3 位:非标准间距 软件中的大多数空格都不会影响程序的性能。除少数使用间距指示代码块的语言(如 Python)外,大多数空格对程序行为的影响为零。尽管如此,仍然有一些得了强迫症的程序员会数空格,并坚持认为它们很重要。曾有这样一位程序员以最严肃的口吻告诉我的老板,说我正在写“非标准代码”,还说他一眼就看出来了。我的错咯?因为我没在等号的两侧放置空格,违反了 ESLint space-infix-ops 规则[1]。 有时候你只要操心那些更深层的内容就行了,谁管什么空格的位置。也许你担心数据库过载,也许你担心空指针可能会让你的代码崩溃。一套代码中,几乎所有的部分都比空格更重要,就算那些喜欢走形式的标准委员会写出来一大堆规则来限制这些空格或制表符的位置,那又如何呢。 令人欣喜的是,网上可以找到一些很好用的工具来自动重新格式化你的代码,让你的代码遵守所有精心定义的 linting 规则。人类不应该在这种事情上浪费时间和脑细胞。如果这些规则这么重要,我们就应该用工具来解决这些问题。 不良的编程习惯第 4 位:使用 goto 禁止使用 goto 的规则可以追溯到许多结构化编程工具还没有出现的时代。如果程序员想创建一个循环或跳转到另一个例程,则需要键入 goto,后跟一个行号。多年之后,编译器团队开始允许程序员使用字符串标签来代替行号。这在当时被认为是一项热门的新特性。 有的人把这样做法的结果称为“意大利面条式代码”。因为以后没人能读懂你的代码,没人搞得清楚执行路径。成为一团混乱的线程,缠结在一起。Edsger Dijkstra 写过一篇题为“我们认为 goto 声明是有害的”的一篇文章[2],号召大家拒绝使用这个命令。 但是绝对分支并不是问题所在,问题在于它产生的那堆纠缠的结果。一般来说,精心设计的 break 或 return 能提供有关该位置的代码执行情况的非常清晰的陈述。有时,将 goto 添加到一个 case 语句中所生成的东西与联 if-then-else 块的相比,结构更正确的列表理解起来更容易。 也有反例。苹果 SSL 堆栈中的“goto fail”安全漏洞[3]就是一个很好的例子。但是,如果我们谨慎地避免 case 语句和循环中出现的一些问题,我们就可以插入很好用的绝对跳转,使代码读者更容易理解正在发生的事情。有时我们可以放一个 break 或 return,不仅更简洁,而且大家读起来更愉快,除了那些讨厌 goto 的人们。 不良的编程习惯第 5 位:不声明类型 热爱类型化语言的人们有他们的理由。当我们为每个变量的数据类型添加清晰的声明时,我们会编写更好,错误更少的代码。花点时间来阐明类型,就可以帮助编译器在代码开始运行之前标记出愚蠢的错误。这可能会很痛苦,但也会有回报。这是一种编程的笨办法,就是为了避免错误。 时代变了。许多较新的编译器已经足够聪明了,它们可以在查看代码时推断出类型。它们可以在代码中前后移动,最后确认变量应该是 string 或 int,抑或是其他类型。而且,如果推断出来的这些类型没法对齐,则编译器会给出错误标志。它们不需要我们再类型化变量了。 换句话说,我们可以省略一些最简单的声明,然后就能轻松节省一些时间了。代码变得更简洁,代码读者也往往能猜出 for 循环中名为 i 的变量是一个整数。 不良的编程习惯第 6 位:溜溜球代码 程序员喜欢将其称为“yo-yo 代码”。首先,这些值将存储为字符串,然后将它们解析为整数,接下来将它们转换回字符串。这种方法效率极低。你几乎能感受到一大堆额外负载让 CPU 不堪重负的样子。能快速编写代码的聪明程序员会调整自己的代码架构,以最大程度地减少转换。因为他们安排好了计划,他们的代码也能跑得更快。 但不管你信不信,有时溜溜球代码也是有意义的。有的时候,你需要用一个可以在自己的黑匣子里搞定一大堆智能操作的库。有的老板花了很多钱,请好多天才做出来这么一个库。如果这个库需要字符串形式的数据,那么你就得给它字符串,就算你最近刚把数据转换为整数也得再转回去。 当然,你可以重写所有代码以最大程度地减少转换,但这会花费一些时间。有时,代码多运行一分钟、一小时、一天甚至一周也是可以接受的,因为重写代码会花费更多时间。有时候,增加技术债务要比重新建立一笔技术债的成本更低些。 有时这种库里面不是专有代码,而是你很久以前编写的代码。有时,转换一次数据要比重写该库中的所有内容更省事。这种时候你就可以编写悠悠球代码了,不要怕,我们都遇到过这种事情。 不良的编程习惯第7位:编写自己的数据结构 有一条标准规则是,程序员在大二学完数据结构课程后,再也不要编写用于存储数据的代码了。已经有人编写过了我们所需要的所有数据结构,并且他们的代码经过了多年的测试和重新测试。这些结构与语言打包在一起,还可能是免费的。你自己写的代码只会是一堆错误。 但有的时候数据结构库的速度有点缓慢。有时候我们被迫使用的标准结构并不适合我们自己的代码。有时,库会要求我们在使用它的结构之前重新配置数据。有时,这些库带有笨重的保护,还有一些诸如线程锁定之类的特性,而我们的代码并不需要它们。 发生这种情况时就该编写我们自己的数据结构了。有时我们自己的结构会快很多,还可能让我们的代码更整洁,因为我们不需要一大堆额外的代码来重新精确地格式化数据。 不良的编程习惯第 8 位:老式循环 很久以前,创建 C 语言的某人想将所有抽象可能性封装在一个简单的构造中。这个构造开始时要做一些事情,每次循环都要做一些事情,所有事情都完成时还有一些方法来提示我们。当时,这似乎是一种拥有无限可能性的完美语法。 此一时彼一时,如今一些现代评论者只看到了其中的麻烦,发生的事情太多了,所有这些可能性既可能向善也可能作恶。这种构造让阅读和理解代码变得非常困难。他们喜欢更加函数式的的范式,其中没有循环,只有应用到列表的函数,还有映射到某些数据的计算模板。 有时无循环方法更简洁,尤其是当我们只有一个简单的函数和一个数组的时候。但还有些时候,老式的循环要简单得多,因为它可以做更多事情。例如,当你找到第一个匹配项后就立刻停止搜索,这样的代码就简单得多。 此外,要对数据执行多项操作时,映射函数会要求更严格的编码。假设你要对每个数字取绝对值,然后取平方根,最快的方案是先映射第一个函数,然后映射第二个函数,将数据循环两次。 不良的编程习惯第 9 位:在中间打破循环 从有一天开始,一个规则制定小组宣布每个循环都应该有一个“不变项”,就是一个在整个循环中都为真的逻辑语句。当不变量不再为真时,循环就结束了。这是处理复杂循环的好方法,但会带来一些令人抓狂的约束,例如禁止我们在循环中间使用 return 或 break。这条规则是禁止 goto 语句规则的子集。 这个理论很不错,但它通常会导致代码变得更复杂。考虑以下这种简单的情况,其中会扫描一个数组,找出通过测试的一个条目: while (i<a.length){ ... if (test(a[i]) then return a[i]; ... } 喜欢循环不变项的人们宁愿我们添加另一个布尔变量,将其称为 notFound,然后这样用它: while ((notFound) && (i<a.length){ ... if (test(a[i])) then notFound=false; ... } 如果这个布尔名称取得很合适,那就会是一段自我注释得很好的代码。它可以让大家理解起来更容易。但这也增加了复杂性。这还意味着要分配另一个局部变量并阻塞一个寄存器,编译器可能没那么聪明,没法修复这个错误。 有时使用 goto 或 jump 会更简洁。 不良的编程习惯第10位:重载运算符和函数 一些有趣的语言会让你绕一些大弯子,比如说重新定义看起来应该是常量的元素值。拿 Python 来说,至少在 2.7 版及更低版本中,它允许你键入 TRUE=FALSE。这不会引发某种逻辑崩溃,也不会导致宇宙的终结;它只是交换了 TRUE 和 FALSE 的含义。你还可以使用 C 预处理器和其他一些语言来玩这种危险的游戏。还有一些语言允许你重新定义加号之类的运算符。 有时候,在一大段代码中重新定义一个或一些所谓常量,结果效率会更高。有时,老板会希望代码执行完全不同的操作。当然,你可以检查代码,逐一更改对应的部分,也可以干脆重新定义现实来节省时间。别人会觉得你是天才。用不着重写庞大的库,只需翻转一下即可。 这里也许应该划一条底线。无论这种做法多有意思,看起来多聪明,你都不应该在家里做实验。这太危险了——我是认真的。

茶什i 2019-12-30 11:01:01 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 云栖号物联网 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 云栖号弹性计算 阿里云云栖号 云栖号案例 云栖号直播