首页服务器nodejs教程,nodejs项目怎么部署到服务器

nodejs教程,nodejs项目怎么部署到服务器

编程之家2026-05-18824次浏览

大家好,nodejs教程相信很多的网友都不是很明白,包括nodejs项目怎么部署到服务器也是一样,不过没有关系,接下来就来为大家分享关于nodejs教程和nodejs项目怎么部署到服务器的一些知识点,大家可以关注收藏,免得下次来找不到哦,下面我们开始吧!

nodejs教程,nodejs项目怎么部署到服务器

node.js安装及环境配置超详细教程【Windows系统安装包方式】

Step1:下载安装包

访问nodejs.org/zh-cn/download/,选择与电脑系统及位数相匹配的.msi(LTS长期稳定版)安装包。.msi与.zip格式的主要区别在于,.msi格式的安装程序包含自动安装功能。

下载方式包括官网直接下载页面下载或首页直接下载。

Step2:安装程序

双击下载的.msi文件开始安装,选择默认配置,安装路径通常在C:\Program Files,可自定义修改。安装路径默认为C:\Program Files,用户可根据需要调整至其他目录如E:\KF\node.js。

选择默认Node.js runtime选项,继续下一步。忽略额外选项,点击Install开始安装,完成后点击Finish完成安装。

nodejs教程,nodejs项目怎么部署到服务器

安装完成后,.msi格式的安装程序会自动将Node.js启动程序添加到系统环境变量Path中。可通过系统属性查看验证。

Step3:查看

在CMD窗口执行node-v命令,显示Node.js的版本信息,表明已成功添加到全局系统变量中。检查npm版本执行npm-v,使用全局包时路径默认为C:\Users\Administrator\AppData\Roaming\npm\node_modules。

常用命令包括但不限于:

Step4:环境配置

打开安装目录(默认为C:\Program Files\nodejs),新建文件夹node_global和node_cache。在CMD中输入npm config set prefix"你的路径 node_global"和 npm config set cache"你的路径 node_cache",将路径设置为新建的文件夹。

nodejs教程,nodejs项目怎么部署到服务器

以管理员权限运行CMD,设置环境变量NODE_PATH为C:\Program Files\nodejs\node_global\node_modules,以便系统识别模块位置。修改用户环境变量的Path,将默认路径C:\Users\Administrator\AppData\Roaming\npm更改为C:\Program Files\nodejs\node_global,并在Path中添加NODE_PATH变量。

测试环境配置,全局安装模块express,确保配置正确。

最后补充:

若遇到npm安装模块时网络问题,可使用阿里团队维护的国内镜像淘宝NPM加速。添加国内镜像源,使用cnpm替代默认的npm命令行工具,支持gzip压缩。

如何用nodejs搭建web服务器

使用Node.js搭建Web服务器是学习Node.js比较全面的入门教程,因为实现Web服务器需要用到几个比较重要的模块:http模块、文件系统、url解析模块、路径解析模块、以及301重定向技术等,下面我们就一起来学习如何搭建一个简单的Web服务器。

作为一个Web服务器应具备以下几个功能:

1、能显示以.html/.htm结尾的Web页面

2、能直接打开以.js/.css/.json/.text结尾的文件内容

3、显示图片资源

4、自动下载以.apk/.docx/.zip结尾的文件

5、形如,则查找b目录下是否有index.html,如果有就显示,如果没有就列出该目录下的所有文件及文件夹,并可以进一步访问。

6、形如,则作301重定向到,这样可以解决内部资源引用错位的问题。

引入需要用到的几个模块:

//http协议模块varhttp= require('http');//url解析模块varurl= require('url');//文件系统模块varfs= require("fs");//路径解析模块varpath= require("path");

创建服务并在指定的端口监听:

//创建一个服务varhttpServer= http.createServer(this.processRequest.bind(this));//在指定的端口监听服务httpServer.listen(port,function(){console.log("[HttpServer][Start]","runing at http://"+ip+":"+port+"/");console.timeEnd("[HttpServer][Start]");});

在创建服务的时候需要传递一个匿名函数processRequest对请求进行处理,processRequest接收2个参数,分别是request和response, request对象中包含了请求的所有内容,response是用来设置响应头以及对客户端做出响应操作。

processRequest:function(request,response){varhasExt=true;varrequestUrl= request.url;varpathName= url.parse(requestUrl).pathname;//对请求的路径进行解码,防止中文乱码pathName= decodeURI(pathName);//如果路径中没有扩展名if(path.extname(pathName)===''){//如果不是以/结尾的,加/并作301重定向if(pathName.charAt(pathName.length-1)!="/"){pathName+="/";varredirect="http://"+request.headers.host+ pathName;response.writeHead(301,{location:redirect});response.end();return;}//添加默认的访问页面,但这个页面不一定存在,后面会处理pathName+="index.html";hasExt=false;//标记默认页面是程序自动添加的}//获取资源文件的相对路径varfilePath= path.join("http/webroot",pathName);//获取对应文件的文档类型varcontentType=this.getContentType(filePath);//如果文件名存在fs.exists(filePath,function(exists){if(exists){response.writeHead(200,{"content-type":contentType});varstream= fs.createReadStream(filePath,{flags:"r",encoding:null});stream.on("error", function(){response.writeHead(500,{"content-type":"text/html"});response.end("<h1>500 Server Error</h1>");});//返回文件内容stream.pipe(response);}else{//文件名不存在的情况if(hasExt){//如果这个文件不是程序自动添加的,直接返回404response.writeHead(404,{"content-type":"text/html"});response.end("<h1>404 Not Found</h1>");}else{//如果文件是程序自动添加的且不存在,则表示用户希望访问的是该目录下的文件列表varhtml="<head><meta charset='utf-8'></head>";try{//用户访问目录varfiledir= filePath.substring(0,filePath.lastIndexOf('\\'));//获取用户访问路径下的文件列表varfiles= fs.readdirSync(filedir);//将访问路径下的所以文件一一列举出来,并添加超链接,以便用户进一步访问for(variinfiles){varfilename= files[i];html+="<div><a href='"+filename+"'>"+filename+"</a></div>";}}catch(e){html+="<h1>您访问的目录不存在</h1>"}response.writeHead(200,{"content-type":"text/html"});response.end(html);}}});}

请求处理函数中有几个重点需要说一下:

对于路径中有中文的,浏览器会自动进行编码(英文不变,中文会变),因此在接收到地址后,需要对地址进行解码,否则最后得到的路径和真实路径不相符,

当访问路径不是以具体的文件结尾,并且不是以/结尾,则需要通过重定向加上/,表示当前目录,否则当前路径下的静态资源会找不到

如果访问路径是目录,则列出该目录下所有文件及文件夹,并可以点击访问,为了让中文目录能正常显示,则还要在header中设置charset=utf-8

核心代码就这么多,大概140行左右,完整的代码已上传到github:,

如果要运行demo,打开cmd切换到根目录,运行node start即可。

NodeJs全栈创建多文件断点续传

文章涉及的源代码在GitHub上,查看源代码。

项目安装这是一个Node项目,可以使用常规的方式进行设置,如果已经有一个项目,则可以继续执行该项目,完全没有问题。如果是全新开始,请执行以下操作:

下载并安装Node,它会全局上安装npm;

安装Yeoman,npminstall-gyo,并全局安装脚手架npminstall-ggenerator-norm;

创建项目文件所在的文件夹;

打开终端并使用cd命令导航到项目目录,例如cdmultifile-uploader;

运行命令npminit-y初始化npm项目,生成简单的package.json;

运行命令yonorm初始化项目基础依赖;

使用npminstallexpress--save命令安装express模块。

运行yarnstart,即可打开预览

工作原理现在来了解这个系统是如何工作的,此应用程序有2个流程需要服务器和客户端之间的严格协调。

上传流程:获取新文件,发送有关文件信息到服务器,服务器返回一个密钥(id),在发送文件块时需要使用该密钥(id),允许它跟踪文件并能够在以后发生中断时恢复它上传。

恢复上传流程:向服务器查询提供的名称和密钥(id)的文件的状态,以便服务器可以响应上传停止的块大小,以便上传可以从该点继续。

还有第四个端点,用于获取所有待处理的文件密钥以恢复上传,以防上传停止并且想在几天后恢复。对于本教程,一旦上传并获取ID,会将其保留在客户端以恢复它们,但是如果关闭浏览器选项卡,ID将丢失,并且将无法恢复。

客户端这里的客户端主要是WEB应用端。这个项目的HTML非常简单,修改文件app/index.html,下面是核心的代码。

<divclass="rowmarketing"><divclass="col-lg-12"><labelclass="upload-btn">上传文件<inputtype="file"multipleaccept="video/*"id="file-upload-input"style="display:none"/></label></div></div>这里的重要细节是input属性必须具有multiple属性以允许用户选择多个文件,还可以选择使用accept属性标识允许上传的文件类型。

对于上传文件,通过input的id属性获取元素对象,并为其绑定事件change来监听用户文件的选择。

constelemFileInput=document.getElementById("file-upload-input");elemFileInput.addEventListener("change",(e)=>{//handlefilehere});下面代码定义了uploadFiles方法:

constuploadFiles=(()=>{constURL=``;constENDPOINTS={UPLOAD:`${URL}upload`,UPLOAD_STATUS:`${URL}/upload-status`,UPLOAD_REQUEST:`${URL}/upload-request`,};constdefaultOptions={url:ENDPOINTS.UPLOAD,startingByte:0,fileId:"",onAbort(){},onProgress(){},onError(){},onComplete(){},};return(files,options=defaultOptions)=>{//handlefileobjectshere};})();上面的代码返回一个函数,它接受一个文件列表和一个可选的选项对象来处理上传。涉及的三个API端点如下:

upload:传输文件块

upload-status:查询文件上传状态,如果开始上传和停止或有什么东西中断了,迫使选择一个文件再次上传,这将返回关于文件停止的位置、在中断之前上传了多少块的信息。

upload-request:通知服务器要上传的内容,以便服务器设置密钥并在上传开始时跟踪文件。

选项对上传的各个阶段或状态进行回调(中止、进度、错误和完成),起始字节是从要发起上传的文件流的哪个位置开始,文件id是标识文件的一种方法。

文件上传UI/UX处理在服务器上设置上传端点之前,最好在客户机上处理它,因为这将帮助服务器端更有意义。

对于这一部分,需要一些处理UI的东西。这部分可以很容易地用任何UI库或框架来完成,比如Vue和Angular。

类似于uploadFiles函数,需要与uploadFiles交互并更新UI的uploadAndTrackFiles。uploadAndTrackFiles是一个函数,它获取一个文件列表并调用uploadFiles,然后通过将页面体上的每个文件元素进度指示器附加到progressBox容器中来设置视图。

在内部,它还有所有的回调函数来跟踪和响应每个文件状态。

constuploadAndTrackFiles=(()=>{constprogressBox=document.createElement("div");letuploader=null;constsetFileElement=(file)=>{//createfileelementhere};constonProgress=(e,file)=>{};constonError=(e,file)=>{};constonAbort=(e,file)=>{};constonComplete=(e,file)=>{};return(uploadedFiles)=>{[...uploadedFiles].forEach(setFileElement);document.body.appendChild(progressBox);uploader=uploadFiles(uploadedFiles,{onProgress,onError,onAbort,onComplete,});};})();从change事件侦听器中调用uploadAndTrackFiles传递文件列表。

elemFileInput.addEventListener("change",(e)=>{uploadAndTrackFiles(e.currentTarget.files);e.currentTarget.value="";});现在要做的一件事是清除之后的input的值,这样浏览器就就不会阻止用户添加更多的文件。到目前为止,可以回到uploadFiles函数中处理上传。

文件上传逻辑回到uploadFiles函数,循环遍历文件列表,并调用处理请求初始化的uploadFile。发起请求后,将返回一个对象,返回的对象为公开函数,当使用文件调用该函数集。

constuploadFiles=(()=>{constURL=``;constENDPOINTS={UPLOAD:`${URL}upload`,UPLOAD_STATUS:`${URL}/upload-status`,UPLOAD_REQUEST:`${URL}/upload-request`,};constdefaultOptions={url:ENDPOINTS.UPLOAD,startingByte:0,fileId:"",onAbort(){},onProgress(){},onError(){},onComplete(){},};constfileRequests=newWeakMap();constuploadFile=(file,options)=>{};constabortFileUpload=(file)=>{};constretryFileUpload=(file)=>{};constclearFileUpload=(file)=>{};constresumeFileUpload=(file)=>{};return(files,options=defaultOptions)=>{[...files].forEach((file)=>{uploadFile(file,{...defaultOptions,...options});});return{abortFileUpload,retryFileUpload,clearFileUpload,resumeFileUpload,};};})();因为可以同时上传多个文件,将定义WeakMap(与Map相比,键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收)类型的变量fileRequests来跟踪所有文件。

uploadFile函数只是让服务器知道它应该期待一个文件很快被上传,并提供文件名。

constuploadFiles=(()=>{constURL=``;constENDPOINTS={UPLOAD:`${URL}upload`,UPLOAD_STATUS:`${URL}/upload-status`,UPLOAD_REQUEST:`${URL}/upload-request`,};constdefaultOptions={url:ENDPOINTS.UPLOAD,startingByte:0,fileId:"",onAbort(){},onProgress(){},onError(){},onComplete(){},};constfileRequests=newWeakMap();constuploadFile=(file,options)=>{};constabortFileUpload=(file)=>{};constretryFileUpload=(file)=>{};constclearFileUpload=(file)=>{};constresumeFileUpload=(file)=>{};constuploadFileChunks=(file,options)=>{};constuploadFile=(file,options)=>{returnfetch(ENDPOINTS.UPLOAD_REQUEST,{method:"POST",headers:{"Content-Type":"application/json",},body:JSON.stringify({fileName:file.name,}),}).then((res)=>res.json()).then((res)=>{options={...options,...res};fileRequests.set(file,{request:null,options});uploadFileChunks(file,options);}).catch((e)=>{options.onError({...e,file});});};return(files,options=defaultOptions)=>{[...files].forEach((file)=>{uploadFile(file,{...defaultOptions,...options});});return{abortFileUpload,retryFileUpload,clearFileUpload,resumeFileUpload,};};})();一旦服务器用文件id进行响应,它就会更新函数,并使用请求选项创建一个文件请求空记录,以备后续重试。一旦这些都设置好了,它就会调用带有文件和更新选项的uploadFileChunks,这些选项将实际处理上传。

在这里,首先初始化表单数据和请求,然后从起始字节点开始对文件进行切片。

文件是一个Blob类型,它让用TypedArray来切片文件字节,这就是如何跟踪从哪一点开始上传文件服务器会负责把文件一块一块地放在一起。

constuploadFileChunks=(file,options)=>{constformData=newFormData();constreq=newXMLHttpRequest();constchunk=file.slice(options.startingByte);formData.append("chunk",chunk,file.name);formData.append("fileId",options.fileId);req.open("POST",options.url,true);req.setRequestHeader("Content-Range",`bytes=${options.startingByte}-${options.startingByte+chunk.size}/${file.size}`);req.setRequestHeader("X-File-Id",options.fileId);req.onload=(e)=>{//当请求状态不是200时被调用//这将只把200视为成功,其他的都是失败if(req.status===200){options.onComplete(e,file);}else{options.onError(e,file);}};req.upload.onprogress=(e)=>{constloaded=options.startingByte+e.loaded;options.onProgress({...e,loaded,total:file.size,percentage:(loaded*100)/file.size,},file);};req.ontimeout=(e)=>options.onError(e,file);req.onabort=(e)=>options.onAbort(e,file);req.onerror=(e)=>options.onError(e,file);fileRequests.get(file).request=req;req.send(formData);};然后,通过提供块的名称(即文件名)和文件id与服务器通信,并通过在将要发送的表单数据中设置这些属性。

当使用XMLHttpRequest时,需要打开一个请求,在这里发起一个POST请求,设置一些头信息。

Content-Range:这是与服务器通信的方式发送的文件字节的范围。该信息对服务器很重要,以便知道如何将文件放回一起并验证请求。

X-File-Id:传递文件id的另一种方式。

一旦设置好请求,就用传递事件和文件Blob的选项回调来映射上传进度事件。

一旦上传完成,就会触发load事件。

当请求接收到更多数据时,就会触发progress事件,从那里可以提取到目前为止上传的总字节数,并计算上传进度百分比。

timeout和error将被视为失败;

当触发中止以暂停上传时,中止将被触发。

接下来要做的就是使用WeakMap中的实际请求更新文件请求并发送表单数据。

文件恢复上传逻辑恢复上传的逻辑要简单得多,这里,所要做的就是使用提供的文件从WeakMap中获取文件请求,并将文件id和名称作为查询参数传递到服务器上查询该文件的上传状态。

有了状态(之前上传的总字节)后,调用uploadFileChunks函数,提供开始上传的字节。

constresumeFileUpload=(file)=>{constfileReq=fileRequests.get(file);if(fileReq){returnfetch(`${ENDPOINTS.UPLOAD_STATUS}?fileName=${file.name}&fileId=${fileReq.options.fileId}`).then((res)=>res.json()).then((res)=>{uploadFileChunks(file,{...fileReq.options,startingByte:Number(res.totalChunkUploaded),});}).catch((e)=>{fileReq.options.onError({...e,file});});}};文件重试上传逻辑文件上传过程中可能会出错,也许网络失去了连接,服务器崩溃了等等。

其逻辑与恢复上传逻辑几乎相同,唯一的区别是在catch块上,重新启动上传,以防文件从未开始上传,并且服务器不知道它。

constretryFileUpload=(file)=>{constfileReq=fileRequests.get(file);if(fileReq){//trytogetthestatusjustincaseitfailedmiduploadreturnfetch(`${ENDPOINTS.UPLOAD_STATUS}?fileName=${file.name}&fileId=${fileReq.options.fileId}`).then((res)=>res.json()).then((res)=>{//ifuploadedwecontinueuploadFileChunks(file,{...fileReq.options,startingByte:Number(res.totalChunkUploaded),});}).catch(()=>{//ifneveruploadedwestartuploadFileChunks(file,fileReq.options);});}};文件暂停上传逻辑要暂停当前上传的文件,需要中止请求。除了抓取文件上传进度,中止请求的能力是使用XMLHttpRequest的第二个原因。

当使用文件调用这个函数时,从WeakMap中获取请求,并使用请求调用abort函数来停止上传。

constelemFileInput=document.getElementById("file-upload-input");elemFileInput.addEventListener("change",(e)=>{//handlefilehere});0这将简单地停止向服务器发送块,然后可以通过调用resumeFileUpload函数继续上传。

文件清除逻辑在上传完成时或之后清除或取消上传,它只会中止请求并清除它,执行清除操作后将无法继续恢复上传。

constelemFileInput=document.getElementById("file-upload-input");elemFileInput.addEventListener("change",(e)=>{//handlefilehere});1上传进度在uploadAndTrackFiles函数,可以定义进度框的内部HTML,它将显示当前有多少文件正在上传,并提供一个上传进度恢复表,告诉有多少文件失败了、成功了、暂停了等等。

还有一个最大化按钮,当点击将展开或折叠上传程序。紧接着,有一个总的文件上传进度条和一个容器,将放置每个文件指示元素和单独的状态和控件。

constelemFileInput=document.getElementById("file-upload-input");elemFileInput.addEventListener("change",(e)=>{//handlefilehere});2一旦接收到文件Blobs,就可以使用它来创建文件元素,方法是调用setFileElement,它创建一个包含文件名、进度条、百分比以及用于处理文件上传的控制按钮的div。

还需要跟踪各个文件元素,以便稍后可以使用文件Blob引用它们。需要跟踪它的大小、状态、百分比和上传的块大小。所有这些细节将用于呈现元素进度细节并相应地更新视图。

constelemFileInput=document.getElementById("file-upload-input");elemFileInput.addEventListener("change",(e)=>{//handlefilehere});3一旦使用了这些元素,就获取了它的控制按钮的引用,并附加了从上传器调用公开方法的单击事件,以控制传递文件的内容。

当清除元素时,需要通过调用updateProgressBox函数来更新进度框元素。这是更新所有上传文件的整体细节的函数。比如所有失败、成功、暂停和上传文件。

constelemFileInput=document.getElementById("file-upload-input");elemFileInput.addEventListener("change",(e)=>{//handlefilehere});4还需要根据文件上传进度事件更新各个文件元素,它只是更新进度条百分比和状态文本消息,并根据文件上传状态切换可见或不可见的按钮。

constelemFileInput=document.getElementById("file-upload-input");elemFileInput.addEventListener("change",(e)=>{//handlefilehere});5现在有了基于上传事件更新元素的函数,需要相应地处理所有文件上传事件。

因此,每当进程事件调用onProgress回调函数时,将使用该文件从setFileElement函数中设置的文件中获取渲染的文件对象,并使用事件细节更新其状态、百分比和块大小,然后调用updateFileElement函数。

constelemFileInput=document.getElementById

nodejs教程和nodejs项目怎么部署到服务器的问题分享结束啦,以上的文章解决了您的问题吗?欢迎您下次再来哦!

直接点击链接就能玩的小游戏,可以赚钱的小游戏ai软件deepseek手机版?deepseek是ai软件吗