찾다
웹 프론트엔드JS 튜토리얼Node.js_node.js에서 HTTP를 사용하여 파일을 업로드하는 방법

개발환경
개발 환경으로는 Visual Studio Express 2013 for Web을 사용하겠지만 Node.js 개발에는 사용할 수 없습니다. 이를 위해서는 Visual Studio용 Node.js 도구를 설치해야 합니다. 설치 후 웹용 Visual Studio Express 2013은 Node.js IDE 환경으로 변환되어 이 애플리케이션을 만드는 데 필요한 모든 것을 제공합니다. 여기에 제공된 지침에 따라 다음이 필요합니다.

  • Node.js Windows 버전을 다운로드하여 설치하세요. 시스템 플랫폼에 적합한 버전인 Node.js(x86) 또는 Node.js(x64)를 선택하세요.
  •  을 다운로드하여 Node.js용 Visual Studio 도구를 설치하세요.

설치가 완료되면 Visual Studio Express 2013 for Web을 실행하고 Node.js 대화형 창을 사용하여 설치를 확인합니다. Node.js 대화형 창은 보기->다른 Windows-> Node.js Interactive Window 아래에서 찾아보세요. Node.js 대화형 창이 실행된 후 모든 것이 괜찮은지 확인하기 위해 몇 가지 명령을 입력해야 합니다.

2015623103550896.png (626×177)

그림 1 Node.js 대화형 창

이제 설치가 확인되었으므로 GB 수준 파일 업로드를 지원하는 Node.js 데몬 생성을 시작할 준비가 되었습니다. 시작하려면 먼저 새 프로젝트를 생성하고 빈 Node.js 웹 애플리케이션 템플릿을 선택합니다. .

2015623103701380.png (628×384)

그림 2 빈 Node.js 웹 애플리케이션 템플릿을 사용하는 새 프로젝트

프로젝트가 생성되면 솔루션 브라우저에 server.js라는 파일과 노드 패키지 관리자(npm)가 표시됩니다

2015623103722152.png (257×444)

그림 3 솔루션 관리자의 Node.js 애플리케이션

server.js 파일에는 Node.js를 사용하여 기본 Hello World 애플리케이션을 만드는 데 필요한 코드가 포함되어 있습니다.

2015623103740566.png (628×275)

그림 4 Hello World 애플리케이션
이제 계속해서 server.js에서 이 코드를 삭제한 다음 Node.js에 G 수준 파일 업로드를 위한 백엔드 코드를 삽입하겠습니다. 다음으로 npm을 사용하여 이 프로젝트에 필요한 일부 종속성을 설치해야 합니다.

  • Express - 단일 페이지, 다중 페이지 및 하이브리드 웹 애플리케이션 구축을 위한 Node.js 웹 애플리케이션 프레임워크
  • 강력함 - 양식 데이터, 특히 파일 업로드 구문 분석을 위한 Node.js 모듈
  • fs-extra - 파일 시스템 상호 작용 모듈

2015623103757338.png (585×424)

그림 5 npm을 사용하여 필수 모듈 설치

모듈이 설치되면 솔루션 탐색기에서 볼 수 있습니다.

2015623103815638.png (287×488)

그림 6 솔루션 탐색기에는 설치된 모듈이 표시됩니다.

다음 단계에서는 솔루션 탐색기에 새 "Scripts" 폴더를 만들고 "workeruploadchunk.js" 및 "workerprocessfile.js"를 폴더에 추가해야 합니다. 또한 jQuery 2.xSparkMD5 라이브러리를 다운로드하여 "Scripts" 폴더에 추가해야 합니다. 마지막으로 "Default.html" 페이지를 추가해야 합니다.

Node.js 백엔드 생성

먼저 Node.js의 "require()" 기능을 사용하여 백그라운드에서 G 수준 파일을 업로드하는 모듈을 가져와야 합니다. "path" 및 "crypto" 모듈도 가져왔습니다. "경로" 모듈은 업로드된 파일 덩어리에 대한 파일 이름을 생성하는 방법을 제공합니다. "crypto" 모듈은 업로드된 파일의 MD5 체크섬을 생성하는 방법을 제공합니다.

// The required modules  
var express = require('express');  
var formidable = require('formidable');  
var fs = require('fs-extra');  
var path = require('path'); 
var crypto = require('crypto');

다음 코드 줄은 기적을 목격하는 순간입니다.

코드 복사 코드는 다음과 같습니다.
var app = express();

这行代码是用来创建express应用的。express应用是一个封装了Node.js底层功能的中间件。如果你还记得那个由Blank Node.js Web应用模板创建的"Hello World" 程序,你会发现我导入了"http"模块,然后调用了"http.CreateServer()"方法创建了 "Hello World" web应用。我们刚刚创建的express应用内建了所有的功能。

现在我们已经创建了一个express应用,我们让它呈现之前创建的"Default.html",然后让应用等待连接。

// Serve up the Default.html page 
app.use(express.static(__dirname, { index: 'Default.html' }));  
 
// Startup the express.js application 
app.listen(process.env.PORT || 1337);  
 
// Path to save the files 
var uploadpath = 'C:/Uploads/CelerFT/';

express应用有app.VERB()方法,它提供了路由的功能。我们将使用app.post()方法来处理"UploadChunk" 请求。在app.post()方法里我们做的第一件事是检查我们是否在处理POST请求。接下去检查Content-Type是否是mutipart/form-data,然后检查上传的文件块大小不能大于51MB。

// Use the post method for express.js to respond to posts to the uploadchunk urls and 
// save each file chunk as a separate file 
app.post('*/api/CelerFTFileUpload/UploadChunk*', function(request,response) {  
 
 if (request.method === 'POST') {  
  // Check Content-Type  
  if (!(request.is('multipart/form-data'))){  
   response.status(415).send('Unsupported media type');  
   return;  
  }  
 
  // Check that we have not exceeded the maximum chunk upload size 
  var maxuploadsize =51 * 1024 * 1024;  
 
  if (request.headers['content-length']> maxuploadsize){  
   response.status(413).send('Maximum upload chunk size exceeded');  
   return;  
  }

 一旦我们成功通过了所有的检查,我们将把上传的文件块作为一个单独分开的文件并将它按顺序数字命名。下面最重要的代码是调用fs.ensureDirSync()方法,它使用来检查临时目录是否存在。如果目录不存在则创建一个。注意我们使用的是该方法的同步版本。

// Get the extension from the file name 
var extension =path.extname(request.param('filename'));  
 
// Get the base file name 
var baseFilename =path.basename(request.param('filename'), extension);  
 
// Create the temporary file name for the chunk 
var tempfilename =baseFilename + '.'+  
request.param('chunkNumber').toString().padLeft('0', 16) + extension + ".tmp";  
 
 
// Create the temporary directory to store the file chunk 
// The temporary directory will be based on the file name 
var tempdir =uploadpath + request.param('directoryname')+ '/' + baseFilename;  
 
// The path to save the file chunk 
var localfilepath =tempdir + '/'+ tempfilename;  
 
if (fs.ensureDirSync(tempdir)) {  
 console.log('Created directory ' +tempdir); 
}

正如我之前提出的,我们可以通过两种方式上传文件到后端服务器。第一种方式是在web浏览器中使用FormData,然后把文件块作为二进制数据发送,另一种方式是把文件块转换成base64编码的字符串,然后创建一个手工的multipart/form-data encoded请求,然后发送到后端服务器。  

所以我们需要检查一下是否在上传的是一个手工multipart/form-data encoded请求,通过检查"CelerFT-Encoded"头部信息,如果这个头部存在,我们创建一个buffer并使用request的ondata时间把数据拷贝到buffer中。

在request的onend事件中通过将buffer呈现为字符串并按CRLF分开,从而从 multipart/form-data encoded请求中提取base64字符串。base64编码的文件块可以在数组的第四个索引中找到。

通过创建一个新的buffer来将base64编码的数据重现转换为二进制。随后调用fs.outputFileSync()方法将buffer写入文件中。

// Check if we have uploaded a hand crafted multipart/form-data request 
// If we have done so then the data is sent as a base64 string 
// and we need to extract the base64 string and save it 
if (request.headers['celerft-encoded']=== 'base64') {  
 
 var fileSlice = newBuffer(+request.headers['content-length']);  
 var bufferOffset = 0;  
 
 // Get the data from the request 
 request.on('data', function (chunk) {  
  chunk.copy(fileSlice , bufferOffset);  
  bufferOffset += chunk.length;  
 }).on('end', function() {  
  // Convert the data from base64 string to binary 
  // base64 data in 4th index of the array 
  var base64data = fileSlice.toString().split('\r\n');  
  var fileData = newBuffer(base64data[4].toString(), 'base64');  
 
  fs.outputFileSync(localfilepath,fileData);  
  console.log('Saved file to ' +localfilepath);  
 
  // Send back a sucessful response with the file name 
  response.status(200).send(localfilepath);  
  response.end();  
 }); 
}

二进制文件块的上传是通过formidable模块来处理的。我们使用formidable.IncomingForm()方法得到multipart/form-data encoded请求。formidable模块将把上传的文件块保存为一个单独的文件并保存到临时目录。我们需要做的是在formidable的onend事件中将上传的文件块保存为里一个名字。

else {  
 // The data is uploaded as binary data.  
 // We will use formidable to extract the data and save it  
 var form = new formidable.IncomingForm();  
 form.keepExtensions = true;  
 form.uploadDir = tempdir;  
 
 // Parse the form and save the file chunks to the  
 // default location  
 form.parse(request, function (err, fields, files) {  
  if (err){  
   response.status(500).send(err);  
   return;  
  }  
 
 //console.log({ fields: fields, files: files });  
 });  
 
 // Use the filebegin event to save the file with the naming convention  
 /*form.on('fileBegin', function (name, file) { 
 file.path = localfilepath; 
});*/  
 
form.on('error', function (err) {  
  if (err){  
   response.status(500).send(err);  
   return;  
  }  
 });  
 
 // After the files have been saved to the temporary name  
 // move them to the to teh correct file name  
 form.on('end', function (fields,files) {  
  // Temporary location of our uploaded file    
  var temp_path = this.openedFiles[0].path;  
 
  fs.move(temp_path , localfilepath,function (err){  
 
   if (err) {  
    response.status(500).send(err);  
    return;  
   }  
   else {  
    // Send back a sucessful response with the file name  
    response.status(200).send(localfilepath);  
    response.end();  
   }  
  });  
 });  
 
// Send back a sucessful response with the file name  
//response.status(200).send(localfilepath);  
//response.end();  
} 
}

app.get()方法使用来处理"MergeAll"请求的。这个方法实现了之前描述过的功能。

// Request to merge all of the file chunks into one file 
app.get('*/api/CelerFTFileUpload/MergeAll*', function(request,response) {  
 
 if (request.method === 'GET') {  
 
  // Get the extension from the file name 
  var extension =path.extname(request.param('filename'));  
 
  // Get the base file name 
  var baseFilename =path.basename(request.param('filename'), extension);  
 
  var localFilePath =uploadpath + request.param('directoryname')+ '/' + baseFilename;  
 
  // Check if all of the file chunks have be uploaded 
  // Note we only wnat the files with a *.tmp extension 
  var files =getfilesWithExtensionName(localFilePath, 'tmp')  
  /*if (err) { 
   response.status(500).send(err); 
   return; 
  }*/ 
 
  if (files.length !=request.param('numberOfChunks')){  
   response.status(400).send('Number of file chunks less than total count');  
   return;  
  }  
 
  var filename =localFilePath + '/'+ baseFilename +extension;  
  var outputFile =fs.createWriteStream(filename);  
 
  // Done writing the file 
  // Move it to top level directory 
  // and create MD5 hash 
  outputFile.on('finish', function (){  
   console.log('file has been written');  
   // New name for the file 
   var newfilename = uploadpath +request.param('directoryname')+ '/' + baseFilename 
   + extension;  
 
   // Check if file exists at top level if it does delete it 
   //if (fs.ensureFileSync(newfilename)) { 
   fs.removeSync(newfilename);  
   //} 
 
   // Move the file 
   fs.move(filename, newfilename ,function (err) {  
    if (err) {  
     response.status(500).send(err);  
     return;  
    }  
    else {  
     // Delete the temporary directory 
     fs.removeSync(localFilePath);  
     varhash = crypto.createHash('md5'),  
      hashstream = fs.createReadStream(newfilename);  
 
     hashstream.on('data', function (data) {  
      hash.update(data)  
     });  
 
     hashstream.on('end', function (){  
      var md5results =hash.digest('hex');  
      // Send back a sucessful response with the file name 
      response.status(200).send('Sucessfully merged file ' + filename + ", "  
      + md5results.toUpperCase());  
      response.end();  
     });  
    }  
   });  
  });  
 
  // Loop through the file chunks and write them to the file 
  // files[index] retunrs the name of the file. 
  // we need to add put in the full path to the file 
  for (var index infiles) {  
   console.log(files[index]);  
   var data = fs.readFileSync(localFilePath +'/' +files[index]);  
   outputFile.write(data);  
   fs.removeSync(localFilePath + '/' + files[index]);  
  }  
  outputFile.end();  
 } 
 
}) ;

注意Node.js并没有提供String.padLeft()方法,这是通过扩展String实现的。

// String padding left code taken from 
// http://www.lm-tech.it/Blog/post/2012/12/01/String-Padding-in-Javascript.aspx 
String.prototype.padLeft = function (paddingChar, length) {  
 var s = new String(this);  
 if ((this.length< length)&& (paddingChar.toString().length > 0)) {  
  for (var i = 0; i < (length - this.length) ; i++) {  
   s = paddingChar.toString().charAt(0).concat(s);  
  }  
 }  
 return s; 
} ;

其中一件事是,发表上篇文章后我继续研究是为了通过域名碎片实现并行上传到CeleFT功能。域名碎片的原理是访问一个web站点时,让web浏览器建立更多的超过正常允许范围的并发连接。 域名碎片可以通过使用不同的域名(如web1.example.com,web2.example.com)或者不同的端口号(如8000, 8001)托管web站点的方式实现。

示例中,我们使用不同端口号托管web站点的方式。

我们使用 iisnode 把 Node.js集成到 IIS( Microsoft Internet Information Services)实现这一点。 下载兼容你操作系统的版本 iisnode (x86) 或者  iisnode (x64)。 下载 IIS URL重写包。

一旦安装完成(假定windows版Node.js已安装),到IIS管理器中创建6个新网站。将第一个网站命名为CelerFTJS并且将侦听端口配置为8000。

2015623103842932.png (546×529)

图片7在IIS管理器中创建一个新网站

然后创建其他的网站。我为每一个网站都创建了一个应用池,并且给应用池“LocalSystem”级别的权限。所有网站的本地路径是C:\inetpub\wwwroot\CelerFTNodeJS。

2015623103905433.png (628×395)

图片8 文件夹层级

我在Release模式下编译了Node.js应用,然后我拷贝了server.js文件、Script文件夹以及node_modules文件夹到那个目录下。
 要让包含 iisnode 的Node.js的应用工作,我们需要创建一个web.config文件,并在其中添加如下得内容。

 

<defaultDocument> 
 <files> 
  <add value="server.js" /> 
 </files> 
 </defaultDocument> 
 
 <handlers> 
 <!-- indicates that the server.js file is a node.js application to be handled by the  
 iisnode module -->  
 <add name="iisnode" path="*.js" verb="*" modules="iisnode" /> 
 </handlers> 
 
 <rewrite> 
 <rules> 
  <rule name="CelerFTJS"> 
  <match url="/*" /> 
  <action type="Rewrite" url="server.js" /> 
  </rule> 
 
  <!-- Don't interfere with requests for node-inspector debugging -->  
  <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true"> 
  <match url="^server.js\/debug[\/]&#63;" /> 
  </rule> 
 </rules> 
 </rewrite>

web.config中各项的意思是让iisnode处理所有得*.js文件,由server.js 处理任何匹配"/*"的URL。 

2015623103925540.png (628×210)

 如果你正确的做完了所有的工作,你就可以通过http://localhost:8000浏览网站,并进入CelerFT "Default.html"页面。

下面的web.config项可以改善 iisnode中Node.js的性能。

复制代码 代码如下:
node_env="production" debuggingEnabled="false" devErrorsEnabled="false" nodeProcessCountPerApplication="0" maxRequestBufferSize="52428800" />


 并行上传

为了使用域名碎片来实现并行上传,我不得不给Node.js应用做些修改。我第一个要修改的是让Node.js应用支持跨域资源共享。我不得不这样做是因为使用域碎片实际上是让一个请求分到不同的域并且同源策略会限制我的这个请求。

好消息是XMLttPRequest 标准2规范允许我这么做,如果网站已经把跨域资源共享打开,更好的是我不用为了实现这个而变更在"workeruploadchunk.js"里的上传方法。

// 使用跨域资源共享 // Taken from http://bannockburn.io/2013/09/cross-origin-resource-sharing-cors-with-a-node-js-express-js-and-sencha-touch-app/ 
var enableCORS = function(request,response, next){  
 response.header('Access-Control-Allow-Origin', '*');  
 response.header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');  
 response.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content- 
     Length, X-Requested-With' ) ; 
 
 
 // 拦截OPTIONS方法
 if ('OPTIONS' ==request.method){  
  response.send(204);  
 }  
 else {  
  next();  
 }  
} ;  
 
// 在表达式中使用跨域资源共享
app. use ( enableCORS ) ;

 为了使server.js文件中得CORS可用,我创建了一个函数,该函数会创建必要的头以表明Node.js应用支持CORS。另一件事是我还需要表明CORS支持两种请求,他们是:

    简单请求:

             1、只用GET,HEAD或POST。如果使用POST向服务器发送数据,那么发送给服务器的HTTP POST请求的Content-Type应是application/x-www-form-urlencoded, multipart/form-data, 或 text/plain其中的一个。

          2、HTTP请求中不要设置自定义的头(例如X-Modified等)

    预检请求:

           1、使用GET,HEAD或POST以外的方法。假设使用POST发送请求,那么Content-Type不能是application/x-www-form-urlencoded, multipart/form-data, or text/plain,例如假设POST请求向服务器发送了XML有效载荷使用了application/xml or text/xml,那么这个请求就是预检的。

            2、在请求中设置自定义头(比如请求使用X-PINGOTHER头)。

在我们的例子中,我们用的是简单请求,所以我们不需要做其他得工作以使例子能够工作。

在  "workeruploadchunk.js" 文件中,我向  self.onmessage 事件添加了对进行并行文件数据块上传的支持. 

// We are going to upload to a backend that supports parallel uploads. 
// Parallel uploads is supported by publishng the web site on different ports 
// The backen must implement CORS for this to work 
else if(workerdata.chunk!= null&& workerdata.paralleluploads ==true){  
 if (urlnumber >= 6) {  
  urlnumber = 0;  
 }  
 
 if (urlcount >= 6) {  
  urlcount = 0;  
 }  
 
 if (urlcount == 0) {  
  uploadurl = workerdata.currentlocation +webapiUrl + urlnumber;  
 }  
 else {  
  // Increment the port numbers, e.g 8000, 8001, 8002, 8003, 8004, 8005 
  uploadurl = workerdata.currentlocation.slice(0, -1) + urlcount +webapiUrl +  
  urlnumber;  
 }  
 
 upload(workerdata.chunk,workerdata.filename,workerdata.chunkCount, uploadurl,  
 workerdata.asyncstate);  
 urlcount++;  
 urlnumber++; 
 }

이 정보를 파일 업로드 작업자에게 보낼 것이기 때문에 Default.html 페이지에 현재 URL을 저장했습니다.

  • 이 정보를 활용하여 포트 수를 늘리고 싶습니다
  • CORS 요청을 한 후 XMLHttpRequest 객체에 전체 URL을 보내야 합니다.


코드 복사 코드는 다음과 같습니다.

// Save current protocol and host for parallel uploads


"font-family: 'Lucida Console'; font-size: 8pt;">var currentProtocol = window.location.protocol;


"font-family: 'Lucida Console'; font-size: 8pt;">var currentHostandPort = window.location.host;


"font-family: 'Lucida Console'; font-size: 8pt;">var currentLocation = currentProtocol + "//" + currentHostandPort;



아래 코드는 업로드 메시지에 대한 수정 사항을 보여줍니다.



// 웹워커에게 메시지 보내기 및 업로드

"배경색: #ffff99; 글꼴 계열: 'Lucida 콘솔'; 글꼴 크기: 8pt;">케이스 '업로드'< ;span style="배경 색상: #ffff99; 색상: #339933; 글꼴 계열: 'Lucida 콘솔'; 글꼴 크기: 8pt;">:

// 백엔드가 병렬 업로드를 지원하는지 확인하세요

var 병렬 업로드 =false; 
if ($('#select_parallelupload').prop('checked')) { 
        병렬 업로드 = true; 

 
uploadworkers[data.id].postMessage({ 'chunk': data.blob, 'filename':data.filename, 
'디렉터리': $("#select_directory").val(), 'chunkCount':data.chunkCount, 
'asyncstate':data.asyncstate,'paralleluploads':paralleluploads, '현재 위치': 
currentLocation, 'id': data.id }); 
휴식;

CelerFT는 CelerFT를 接口来支持并行上传.

2015623104005997.png (628×344)

유유한 CelerFT

这个项目的代码可以再我的 github 资源库上找到

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Apr 15, 2025 am 12:16 AM

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지Apr 14, 2025 am 12:05 AM

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

JavaScript 엔진 : 구현 비교JavaScript 엔진 : 구현 비교Apr 13, 2025 am 12:05 AM

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

브라우저 너머 : 실제 세계의 JavaScript브라우저 너머 : 실제 세계의 JavaScriptApr 12, 2025 am 12:06 AM

실제 세계에서 JavaScript의 응용 프로그램에는 서버 측 프로그래밍, 모바일 애플리케이션 개발 및 사물 인터넷 제어가 포함됩니다. 1. 서버 측 프로그래밍은 Node.js를 통해 실현되며 동시 요청 처리에 적합합니다. 2. 모바일 애플리케이션 개발은 재교육을 통해 수행되며 크로스 플랫폼 배포를 지원합니다. 3. Johnny-Five 라이브러리를 통한 IoT 장치 제어에 사용되며 하드웨어 상호 작용에 적합합니다.

Next.js (백엔드 통합)로 멀티 테넌트 SAAS 애플리케이션 구축Next.js (백엔드 통합)로 멀티 테넌트 SAAS 애플리케이션 구축Apr 11, 2025 am 08:23 AM

일상적인 기술 도구를 사용하여 기능적 다중 테넌트 SaaS 응용 프로그램 (Edtech 앱)을 구축했으며 동일한 작업을 수행 할 수 있습니다. 먼저, 다중 테넌트 SaaS 응용 프로그램은 무엇입니까? 멀티 테넌트 SAAS 응용 프로그램은 노래에서 여러 고객에게 서비스를 제공 할 수 있습니다.

Next.js (Frontend Integration)를 사용하여 멀티 테넌트 SaaS 응용 프로그램을 구축하는 방법Next.js (Frontend Integration)를 사용하여 멀티 테넌트 SaaS 응용 프로그램을 구축하는 방법Apr 11, 2025 am 08:22 AM

이 기사에서는 Contrim에 의해 확보 된 백엔드와의 프론트 엔드 통합을 보여 주며 Next.js를 사용하여 기능적인 Edtech SaaS 응용 프로그램을 구축합니다. Frontend는 UI 가시성을 제어하기 위해 사용자 권한을 가져오고 API가 역할 기반을 준수하도록합니다.

JavaScript : 웹 언어의 다양성 탐색JavaScript : 웹 언어의 다양성 탐색Apr 11, 2025 am 12:01 AM

JavaScript는 현대 웹 개발의 핵심 언어이며 다양성과 유연성에 널리 사용됩니다. 1) 프론트 엔드 개발 : DOM 운영 및 최신 프레임 워크 (예 : React, Vue.js, Angular)를 통해 동적 웹 페이지 및 단일 페이지 응용 프로그램을 구축합니다. 2) 서버 측 개발 : Node.js는 비 차단 I/O 모델을 사용하여 높은 동시성 및 실시간 응용 프로그램을 처리합니다. 3) 모바일 및 데스크탑 애플리케이션 개발 : 크로스 플랫폼 개발은 개발 효율을 향상시키기 위해 반응 및 전자를 통해 실현됩니다.

JavaScript의 진화 : 현재 동향과 미래 전망JavaScript의 진화 : 현재 동향과 미래 전망Apr 10, 2025 am 09:33 AM

JavaScript의 최신 트렌드에는 Typescript의 Rise, 현대 프레임 워크 및 라이브러리의 인기 및 WebAssembly의 적용이 포함됩니다. 향후 전망은보다 강력한 유형 시스템, 서버 측 JavaScript 개발, 인공 지능 및 기계 학습의 확장, IoT 및 Edge 컴퓨팅의 잠재력을 포함합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구