毕业设计(论文)-多类型互联网前端开发技术的研究与应用.doc_第1页
毕业设计(论文)-多类型互联网前端开发技术的研究与应用.doc_第2页
毕业设计(论文)-多类型互联网前端开发技术的研究与应用.doc_第3页
毕业设计(论文)-多类型互联网前端开发技术的研究与应用.doc_第4页
毕业设计(论文)-多类型互联网前端开发技术的研究与应用.doc_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

盐城师范学院毕业设计盐 城 师 范 学 院毕业设计多类型互联网前端开发技术的研究与应用学生姓名 学 院 信息工程学院 专 业 数字媒体技术 班 级 12(1) 学 号 指导教师 年 月 日多类型互联网前端开发技术的研究与应用摘 要随着移动互联技术的快速发展,Web标准不断完善,用户对产品体验的要求日益攀升,导致Web应用交互日趋复杂。课题采用当今服务端最热门的Node.js技术,在保持了与传统技术相互兼容的前提下,Node.js采用了基于事件驱动的异步式I/O模型,结合Node.js的模块管理工具NPM,实现了在处理响应事件、多个并发请求上的突破,并保持了流动性的用户体验,对降低HTTP服务器的并发压力、提高吞吐量方面有着极其重要的作用。【关键词】Node.js;异步式I/O;高并发;事件驱动; 全套设计加扣 3012250582Design and development of universal salary management system oriented to AndroidAbstractWith the rapid development of mobile Internet technology, Web standards continue to improve, the users demand for product experience is increasing, resulting in Web application interaction is becoming increasingly complex. Topic by todays server the most popular node.js technology, while maintaining the premise of mutually compatible with traditional technology, node.js adopted based on event driven asynchronous I / O model, combined with node.js module management tool - NPM, the realization of the response to the event, multiple concurrent requests on the breakthrough in the treatment, and to maintain the liquidity of the user experience, to reduce the concurrent pressure of the HTTP server, has an extremely important role to improve the throughput.Key words Node.js; Asynchronous I/O; High concurrency; Asynchronous I/O; Event driven;目 录1 绪论11.1研究背景及意义11.2 研究的思路与内容12 Node.js技术22.1 Node.js简介22.2 Node.js工作原理32.2.1 NPM包管理器42.2.2 事件驱动编程42.2.3 异步式I/O43异步式I/O与同步式I/O模型的研究43.1 阻塞与线程63.1.1单线程非阻塞的事件编程模式63.1.2 异步式I/O与同步式I/O的特点73.2 单元测试83.2.1 Node.js两种方式读取文件.84传统I/O设计模型114.1 传统I/O设计模型的异同114.2 高性能I/O设计模式134.2.1 Reactor模式多路复用I/O135实时语音咨询单页面应用145.1语音咨询请求服务145.1.1语音咨询架构设计145.1.2 API接口封装145.1.3异步式I/O请求服务165.1.4 路由设计165.1.5 核心功能模块176结论21结束语23参考文献24盐城师范学院毕业设计1 绪论1.1研究背景及意义随着移动互联的普及,通过互联网进行电子商务与信息获取已成为人们生活中不可或缺的一部分。但由于互联网前端开发技术类型众多,在兼容性和扩展性上都无法适应需求,大大降低了应用平台的效率和用户体验,尤其在系统进行I/O操作(网络通信和磁盘读写)时更为严重。如何在现有的基础上优化用户体验,开发人员不断做出努力和尝试。在单核时代,PHP之类的语言大多采用多线程或者是多进程来解决并发请求,这样做增加了频繁的上下文切换,同时也加大了成本。这时Node.js应运而生,采用单线程非阻塞的异步式的I/O请求方式,避免了频繁的上下文切换。1.2研究的思路与内容首先对Node.js技术出现的背景进行简单概括,对Node.js基于事件驱动的异步式I/O模型的原理进行详细分析并研究测试,总结该模型在处理高并发请求时的性能优势。接着,研究了Node.js的组织架构,将Node.js的I/O模型与传统I/O模型进行对比,详述了传统多线程多进程模型的弊端。最后,在基于Node.js平台下构建一个实时语音咨询应用,使用Node.js核心技术单线程异步式I/O的请求加上融云MQTT推送协议,在系统应用架构设计、API接口封装、路由设计以及核心功能模块上进行详细阐述,从而实现语音信息精准及时的推送。2 Node.js技术2.1 Node.js简介Javascript作为服务端的脚本语言不是一门新技术,协程应用开发框架FibJS、RingoJS等等都在这方面做出过努力和尝试。但它们在处理并发请求和I/O操作时始终无法完成突破,而Node.js则大胆的应用单线程异步式I/O请求,让前端开发工程师看到了从前端写到后端的希望。传统的Web开发响应模式客户端(C端)主动发起通信而服务端(S端)被动返回。而Node.js在实时的Web应用上采用基于 WebSocket 的推送技术,在客户端和服务端均可发起网络通信,两者之间能够自由地交换数据。图2-1传统Web响应模式Node.js 是一个基于Chrome V8引擎的 JavaScript 运行环境,采用事件驱动、非阻塞式 I/O 的模型,从而让自身变得轻量高效1。此外,采用单线程的Node.js处理并发请求的流程如下:第一步:为监听套接口在反应堆中注册一个事件,该事件调用对应的回调,接受这个请求连接,然后为这个连接创建连接对象,统一管理;第二步:为此连接创建buffer对象,同时注册对应的读写错误事件的回调(上层对于buffer的读写事件回调都是业务层来控制的);第三步:每个请求在加入监听队列后是离散的,每一个事件的先后顺序跟它达到的顺序有关;第四步:如果有事件发生会调用回调来处理,理论上无阻塞情况减少了很多CPU的等待时间,这部分时间用于处理真正的业务。所以异步模型能够带来很高的CPU处理能力,减少等待,单位时间处理的事件更多。图2-1Node.js处理并发流程图而传统的多线程在处理并发请求时,则是每增加一个请求,系统都会为该请求分配一条线程。为了处理业务,采用多线程模型不得不消耗更多的内存而且增加了频繁的上下文切换所带来的切换开销。图2-2多线程并发请求2.2 Node.js工作原理Node.js的工作原理如下:第一:Node.js采用异步式I/O和事件驱动代替传统的多线程模型,由此带来HTTP服务器性能的提升;第二:Node.js使用V8作为Javascript的引擎,采用高效的Libev和Libeio库来支持事件驱动和异步式I/O;第三:在Libev和Libeio的基础上抽象出Libuv层,Libuv层使用了windows的IOCP机制,实现跨平台的高性能应用。图2-3Node.js架构图2.2.1 NPM包管理器目前非常流行的NPM模块有如下几个:表2-1 常用的NPM模块expressNode.js Web应用框架,应用普遍connectConnect 是一个Node.js 的 HTTP 服务拓展框架,提供一个高性能的“插件”集合,以中间件闻名socket.io目前服务端最流行的websocket 组件Jade流行的模板引擎之一。并且是 Express.js 的默认模板引擎mongo封装了 MongoDB 的的各种APIforever可能是用来确保 node 脚本持续运行的最流行的工具redisRedis 的客户端函数库underscore最流行的 JavaScript 工具库 , 用于 Node.js 的封装包2.2.2事件驱动编程传统的Web服务大多是采用线程模型,利用Apache或者其他的服务器,等待接受连接,该连接会一直等待所有的请求完成后再断开连接。如果遇到I/O操作或者对数据库进行访问,Web服务器就会阻塞这个I/O请求,想要提高性能,只能启动更多的Server实例。在开发Web应用时,当对某个DOM添加事件时,只需要在当前DOM元素上注册一个事件监听器即可10。当用户触发该事件时,注册在该事件上的Javascript方法就会被执行。这种方法是异步执行的,在高性能的并发网络领域应用十分普遍。而Node.js使用的是事件驱动编程模型。var http = require(http); /引入http模块var url = require(url); /引入url模块http.createServer(function (req, res) /创建http服务器var urlObj = url.parse(req.url, true); / 获取被代理的 URL var urlToProxy = urlObj.query.url; / 格式化代理的 URLif (!urlToProxy) res.statusCode = 400; res.end(URL地址。); / 返回信息 else console.log(处理代理请求: + urlToProxy); / 打印调试信息 var parsedUrl = url.parse(urlToProxy); http.get(opt, function(pres) / 请求被代理 URL 的内容 res.statusCode = pres.statusCode; var headers = pres.headers; for (var key in headers) res.setHeader(key, headerskey); / 设置头信息 pres.on(data, function(chunk) res.write(chunk); / 写回数据 ); ); ).listen(8080, ); /监听端口console.log(服务在 8080 端口启动。);上述实现过程主要分以下几步:第一步:通过http模块创建一个http服务器。第二步:通过listen()方法就可以让该 HTTP 服务器在特定端口监听。第三步:在createServer()方法中传入的参数是 HTTP 请求的响应方法。2.2.3异步式I/O对于异步式I/O请求与事件驱动的架构设计,Node.js采用单线程模型,对于所有的I/O操作,均采用异步式的请求方法,以此避免了频繁的上下文切换以及对内存的占用。3异步式I/O与同步式I/O模型的研究3.1阻塞与线程3.1.1单线程非阻塞的事件编程模式node.js开发指南对阻塞的定义为:“线程在执行中如果遇到I/O操作(如磁盘读写或网络通信),通常要耗费较长的时间,这时操作系统会剥夺这个线程的CPU控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为阻塞。当I/O操作完毕时,操作系统将这个线程的阻塞状态解除,恢复其对CPU的控制权,令其继续执行1。图3-1 同步阻塞I/O请求Node.js异步式的I/O采取的策略是:当遇到 I/O 操作(包括字盘读写和网络通信,通常耗时较大)时,不会以阻塞的方式等待当前请求操作的完成或数据的返回,而只是将发送的请求告知操作系统,线程则继续执行下一条语句。请求的结果是通过回调函数返回。3.1.2异步式I/O与同步式I/O的特点表3-1同步式I/O和异步式I/O的特点同步式 I/O 和异步式 I/O 的特点同步式I/O(阻塞式)异步式 I/O利用多线程提供吞吐量单通过功能划分利用多核CPU通过事件片分割利用多核CPU可以将单进程绑定到单核CPU需要由操作系统调度使用多核 CPU可以充分利用CPU资源难以充分利用CPU资源内存轨迹小,数据局部性强符合线性的编程思维不符合传统编程思维3.2单元测试3.2.1 Node.js两种方式读取文件首先,Node.js同步读取文件的测试代码如下:var fs = require(fs); /同步阻塞的文件读取var data = fs.readFileSync(./test.txt,utf-8); /读取静态文本console.log(data);/打印信息console.log(end文件读取完毕);执行命令,运行结果如下所示:Test文件 /首先打印的信息end文件读取完毕 /其次打印的信息首先打印出读取到的data数据,然后打印结束语句。其次,Node.js异步读取文件操作的测试代码如下:fs.readFile(./test.psd, utf-8, function(err, data) /读取静态文本if (err) console.error(err);/抛出错误信息 else console.log(异步非阻塞读取文件完毕1); /打印消息);console.log(测试文件读取); /打印调试信息执行命令,运行结果如下所示:测试文件读取 /首先打印的信息异步非阻塞读取文件完毕1 /其次打印的信息从测试执行结果的顺序来看,这和Javascript代码执行结果的顺序相反。因为Node.js采用异步非阻塞的方式读取文件,当接受到异步I/O请求时,不会在当前等待结果的返回,而是继续执行以后的任务。那么,异步请求的结果是什么时候返回给操作系统的呢?是完成了以后立即返回还是等待后面的任务完成以后再将结果返回给操作系统?因此,提出如下猜想: 猜想一:异步请求的结果处理完成后立即返回给操作系统,并插入到一个正在进行并且等待这个任务结束之后。猜想二:异步请求的结果处理完成后要等待这个线程上所有任务完成后再来将异步请求的结果返回给操作系统。为了验证猜想,构造如下的代码:var fs = require(fs); /引入文件系统fs模块fs.readFile(./test.psd, utf-8, function(err, data) /异步读取文件if (err) console.error(err); else console.log(异步非阻塞读取文件完毕1););console.log(普通的任务);var data = fs.readFileSync(./test.psd,utf-8);console.log(同步阻塞文件读取完毕1);如果 “异步非阻塞读取文件完毕1”这句话可以被打印在中间,这就表明猜想成功,测试结果如下:普通的任务 /首先打印的信息同步阻塞文件读取完毕1 /其次打印的信息异步非阻塞读取文件完毕1 /最后打印的信息结果和预想不一样,表明异步读取文件的结果是在其他任务完成以后才返回。但是这会不会是因为后面的任务执行非常快,而异步读取本来就耗时?经过多方测试,得出异步请求的结果都是在最后被打印。接下来,利用下面的代码来验证猜想二:首先构建两个异步读取文件操作的请求,且被读取的文件大小不同。同时,也加入同步读取文件的操作。fs.readFile(./test.psd, utf-8, function(err, data) /异步读取文件if (err) console.error(err); else console.log(异步非阻塞读取文件完毕1););console.log(普通的任务); /普通任务var data = fs.readFileSync(./test.psd,utf-8); /同步读取文件console.log(同步阻塞文件读取完毕1);fs.readFile(./test.txt, utf-8, function(err, data) /异步读取文件if (err) console.error(err); else console.log(异步非阻塞读取文件完毕2););var data = fs.readFileSync(./test.psd,utf-8);console.log(同步阻塞文件读取完毕2);测试代码的打印结果如下:普通的任务 /首先打印的信息同步阻塞文件读取完毕1 /其次打印的信息同步阻塞文件读取完毕2 /然后打印的信息异步非阻塞读取文件完毕2 /在然后打印的信息异步非阻塞读取文件完毕1 /最后打印的信息该结果充分表明,异步读取文件的结果是在其他任务结束后才返回,并且不断检查事件循环队列列表,通过回调函数把执行的结果返回。通过以上的研究,得出以下的结论:Node.js遇到异步I/O请求时,会将该请求发送给操作系统,然后立即返回并执行之后的语句,执行完成后再进入到事件循环监听队列。当异步式请求完成时,事件循环会通过回调函数完成之后的任务。图3-2 事件循环队列4传统I/O设计模型在遇到磁盘读写或者网络通信时,通常会使用一下五种I/O设计模型:阻塞I/O,非阻塞I/O,多路复用I/O,信号驱动I/O以及异步式的I/O。4.1传统I/O设计模式的异同 (1) 阻塞I/O设计模式传统IO模型。即在遇到I/O操作过程中会发生阻塞现象的模型。当前用户线程会交出CPU的控制权,在阻塞型I/O模式中,当系统调用recv()/recvfrom()函数时,发生在内核中的过程如下:第一步:系统首先检查是否有准备好的数据。如果没有准备好数据,那么系统将处于等待状态。第二步:当数据准备好后,将数据从系统缓冲区复制到用户空间,然后该函数返回。第三步:在应用程序中,当调用recv()函数时,用户空间不一定就已经存在数据,那么此时recv()函数就会处于等待状态。当前线程会交出对CPU控制权10。(2) 非阻塞IO模型。这个模式不断访问内核数据,不会交出CPU的控制权,一直占用。可持续的访问内核数据并判断是否就绪,会造成CPU的占用率特别高。典型的非阻塞IO模型的例子为: while(true)data = socket. recv ();if(data!= error) /在这里处理响应数据break;recv() 接口在被调用后立即返回,返回值代表了不同的含义。表4-1 recv返回值意义返回值返回值意义返回值大于 0表示接受数据完毕返回 0表示连接已经正常断开返回 -1表示 recv 操作还没执行完成(3) 多路复用I/O模型。这个设计模式利用一个线程来控制多个socket,只有当真正有I/O操作时才会占用CPU来进行实际的I/O操作。同时,socket状态在内核进行,效率比较高。对于多路复用I/O模型,需要注意以下几点:第一:对于每一个socket,一般都设置成为non-blocking,当任何一个socket中的数据准备好后,select就会返回。第二:使用select() 的事件驱动模型只用单线程(进程)执行,占用资源少,不消耗太多CPU。(4) 信号驱动IO模型。通过socket注册一个类似的信号函数,执行当前线程,进行实际的I/O操作。图4-2 五种I/O请求的异同4.4 高性能的I/O设计模式4.4.1 Reactor模式多路复用I/OReactor模式模块之间的交互过程是这样的:首先,初始化InitiationDispatcher,同时初始化一个Handle到EventHandle的Map;其次,注册一个EventHandle,建立一个从Handle到EventHandle的映射(Map);然后调用InitiationDispatcher_event()方法,启动事件循环机制,调用select方法防止阻塞; 最后,当有新的连接请求时,产生新的EventHandle,注册到InitiationDispatcher中,处理各个模块之间的交互过程。Reactor模式可概括为以下三点:第一: Reactor模式是基于事件驱动的。第二: Reactor模式有一个或者多个并发源。第三: Reactor模式有一个Service Handler,这个Service Handler会同步的将输入的请求(Event)多路复用的分发给相应的Request Handler。Reactor模式架构如下图所示:图4-3 高效Reactor模式5 实时语音咨询单页面应用如今,越来越多的web网页都采用了单页应用,在浏览器运行中的应用,不需要重复加载。相对于传统多页面应用,单页面有如下优势:第一:给用户更加友好的用户体验。页面内容的改变不需要重新加载整个页面,同时,响应速度也更加迅速。第二:具有桌面应用的即时性,把当前的状态及时通知给用户,显示进度。第三:具备良好的前后端分离特性。SPA和RESTful架构可以一起使用。后端不再负责模板渲染、输出页面工作,前端和各种移动终端地位对等,后端API通用化。服务器的压力也同时减少4。第四:对前端人员Javascript技能要求更高,促使团队技能提升。但是,单页应用不利于SEO的优化,同时存在初次加载时间也相对较多,cookie的保存等问题。5.1 语音咨询请求服务5.1.1 语音咨询架构设计语音咨询业务提供用户在线下单服务,最核心的功能是当前消息的实时性分发,信息的推送使用融云提供的即时通讯云服务。当用户选择服务后(先付费或者后付费),将当前订单推送到律师客户端,由律师抢单完成后续服务。整体的架构主要分为三部分:第一:使用融云提供的推送服务,使相应的业务能够快速获得即时通讯的能力以及一些场景的需要。第二:基于Node.js内置的HTTP服务器,采用异步式的I/O操作,session 存储以及Node.js的数据库更新服务。第三:HTTP服务器接收到用户的请求后,服务器将会直接调用基于Node 的读取服务,从而进行下一步的任务。图5-1 语音咨询架构设计5.1.2 API接口封装表5-1用户登录接口接口名称用户登录接口接口格式http post接口描述用户登录接口urlhttp:/user/login表5-2请求消息字段名称必填说明phone手机号M+86中国大陆verifyCode手机验证码M手机验证码表5-3响应消息字段名称必填说明Code响应结果M1- ok988-请求参数错误desp响应描述M描述tokentokenN登录信息表5-4产品详情接口接口名称产品详情接口接口格式http post接口描述产品详情接口urlhttp:/user/cardDetailInfo表5-5请求消息字段名称必填说明token登录信息M获取登录信息productId产品编号M产品ID表5-6响应消息字段名称必填说明Code响应结果M2- ok988-请求参数错误desp响应描述M描述tokentokenN登录信息5.1.3异步式I/O请求服务Var request = function(service, method, _args, callback)global.pool.acquire(function(err, connection) /从RPC连接线程池中获取活动连接(如果无活动连接,则返回新建立的连接) /处理RPC的请求参数 if(!_args) / 如果无参数则建立一个空数组 _args = ; /空数组 console.log(RPC TO + method + : + _args); /打印相应信息 _args.push(function(err, response) /在请求参数的最后加上回调方法 if(err) /等RPC异步请求返回之后执行 console.log(err) var r = JSON.parse(response); /转为响应的json字符串 console.log(rpc response : + response); if(r.status r.status.code != 1) /判断返回数据在业务层面的正确性 callback(r.status.desp, r); / 回调具体的业务回调逻辑处理函数 else callback(err, r); /执行错误回调函数 /取消连接,释放会连接池 global.pool.release(connection); ); if(_args) /请求RPC接口 connection.clientservicemethod.apply(connection.clientservice,_args); else connection.clientservicemethod.apply(connection.clientservice); );module.exports = request;消息队列推送的实现:(1) 引入amqp模块,amqp模块遵循了AMQP 协议13,该消息队列服务器提供了Node下运行的的客户端环境。因此Node.js的 程序可以通过该模块连接并操作Redis消息队列;(2) HTTP 服务器在接收到不同的请求之后,会根据路由规则做出不同的处理,这些处理函数被封装在相应的回调函数中,只要匹配相应的路由关键字,该消息才会被添加到消息队列中。5.1.4 路由设计路由采用REST风格,Express支持REST风格的请求方式,同时Express是基于Node.js的非常优秀的服务端开发框架。通过URL指定资源,操作包括获取、创建、修改以及删除,与之对应的则是HTTP协议中的GET请求、POST请求、PUT请求以及DELETE请求。相关路由设计如下:表5-1 基于Express的路由设计语音咨询路由设计route.post(/ ,callback)首页route.get(/login, callback)登录route.get(/mqttCount, callback)连接融云服务route.get(/orderList, callback)语音咨询列表route.get(/orderServices, callback)单页应用订单页route.get(/orderDetails, callback)订单详细页route.get(/orderPay, callback)支付页面5.1.5 核心功能模块(1)登录模块loginNode端接口配置/login:title:用户登录接口, /登录接口名称 config:baseurl:API_URL, /登录接口url method:POST, /HTTP请求方式 command:user/login, /url data:body, /请求体 encrypt:false, /是否加密传输,调用登录接口loginSubHttpService.post(/apiLogin?json=1, subData, function (data) if(pid = 0)location.href = _url; /登录判断跳转); 图5-2 登录界面以及登录验证功能描述: 用户输入手机号码作为通行证,获取手机短信验证码即可完成登录。(2):提交用户身份信息模块orderCommissionNode端接口配置/checkPersonalInfo: title: 用户身份信息, /用户身份接口名称 config: baseurl: API_URL, /用户身份接口url method: POST, /HTTP请求方式 command: user/modifyInfo,/url data: body, /HTTP请求体 encrypt: true /HTTP是否加密 ,PersonalInfoHttpService.post(/personalInfo?json=1, , function (data) console.log(data); /打印data数据 var _realUname = data.realName; /获取用户姓名 var _realIdedity = data.cardId; /获取用户身份证图5-3 提交用户身份信息功能描述: 用户填写相应的身份信息以及服务详情,推送到律师端,由律师完成抢单服务。(3):提交语音咨询单模块OrderList Node端接口配置/ placeOrder: title: 用户下单接口, /用户下单接口名称 config: baseurl: API_URL, /用户身份接口url method: POST, /HTTP请求方式 command: user/ placeOrder,/url data: body, /HTTP请求体 encrypt: true /HTTP是否加密httpService.post(/orderList?json=1, productId:parentProductId,function(data) console.log(data); /打印data数据 var num = ductDetailList.length; /获取服务列表长度 $(.orderList).html().attr(productId,parentProductId);/设置相应产品productorId图5-4 语音咨询服务功能: 用户选择语音咨询服务类型,提交订单。律师端收到推送语音信息,给用户拨打语音电话,完成后续服务。 对于程序员来说,异步式的编程风格所带来的大量的回调嵌套所引发的所谓的“回调地狱”,不但让编写的代码看起来臃肿难以阅读,同时,也会让项目更加难以维护。但是可以通过使用promise来解决上述的问题。$(.xx).animate(, function() $(xx).animate(xx,function() /执行指定动画,1000),1000)/使用promise解决上述回调的问题:function animate(dis,time) /定义动画函数 var def = $.Deferred();/定义def变量 $(.boll).animate( left: dis+px /执行动画 ,time, function() def.resolve(time); ); return def; /返回变量$(.boll).on(click,function() $.when( animate(50,1000), /执行动画6 结论综上所述,虽然Node.js现在应用广泛,很多公司都是基于它进行前后端分离开发,但前端开发技术日新月异,必须及时做出突破。在接下来的时间里,希望Node.js能做到以下几个方面的突破或者创新:(1) 单

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论