搜尋
首頁web前端js教程在Node.js中使用HTTP上傳檔案的方法_node.js

開發環境
我們將使用 Visual Studio Express 2013 for Web 作為開發環境, 不過它還不能被用來做 Node.js 開發。為此我們需要安裝 Node.js Tools for Visual Studio。  裝好後 Visual Studio Express 2013 for Web 就會轉變成一個 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 的互動視窗可以再View->Other Windows->Node.js Interactive Window 下找到. Node.js 交互視窗運行後我們要輸入一些指令檢查是否一切OK.

2015623103550896.png (626×177)

Figure 1 Node.js Interactive Window

現在我們已經對安裝進行了驗證,我們現在就可以準備開始創建支援GB級文件上傳的Node.js後台程式了. 開始我們先創建一個新的項目,並選擇一個空的Node.js Web應用程式模板.

2015623103701380.png (628×384)

Figure 2 New project using the Blank Node.js Web Application template

專案建立好以後,我們應該會看到一個叫做 server.js 的文件,還有解決方案瀏覽器裡面的Node包管理器 (npm). 

2015623103722152.png (257×444)

圖3 解決方案管理員裡面的 Node.js 應用程式

server.js 檔案裡面有需要使用Node.js來建立一個基礎的hello world應用程式的程式碼.

2015623103740566.png (628×275)

Figure 4 The Hello World application
 我現在繼續把這段程式碼從 server.js 中刪除,然後在Node.js中穿件G級別檔案上傳的後端程式碼。下面我需要用npm安裝這個專案需要的一些依賴:

  •      Express - Node.js網頁應用程式框架,用於建立單一頁面、多個頁面以及混合網路應用程式
  •      Formidable - 用於解析表單數據,特別是檔案上傳的Node.js模組
  •      fs-extra - 檔案系統互動模組

2015623103757338.png (585×424)

圖5 使用npm安裝所需模組

模組安裝完成後,我們可以從解決方案資源管理器中看到它們。

2015623103815638.png (287×488)

 圖6 解決方案資源管理器顯示已安裝模組

下一步我們需要在解決方案資源管理器新建一個 "Scripts" 資料夾並且新增  "workeruploadchunk.js" 和   "workerprocessfile.js" 到該資料夾。我們還需要下載jQuery 2.x 和  SparkMD5 庫並新增至"Scripts"資料夾。 最後還需要加入 "Default.html" 頁面。

 建立Node.js後台

首先我們需要用Node.js的"require()"函數來匯入在背景上傳G級檔案的模組。注意我也導入了"path"以及"crypto" 模組。 "path"模組提供了產生上傳檔案區塊的檔案名稱的方法。 "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 請求,我需要把完整的 URL 傳送給 XMLHttpRequest 物件.

 

複製程式碼 程式碼如下:

// 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;



下面的程式碼顯示了上傳訊息所做的修改。



// 發送並上傳訊息到 webworker

「背景顏色:#ffff99;字體系列:'Lucida Console';字體大小:8pt;」>case '上傳':

// 檢查後端是否支援並行上傳

varparalleluploads = false; 
if ($('#select_parallelupload').prop('checked')) { 
        並行上傳=真; 

 
uploadworkers[data.id].postMessage({ 'chunk': data.blob, '檔名':data.filename, 
'目錄': $("#select_directory").val(), 'chunkCount':data.chunkCount,
'asyncstate':data.asyncstate,'paralleluploads':paralleluploads,'目前位置':
currentLocation, 'id': data.id }); 
休息;

最後了 CelerFT 介面來支援上傳。

2015623104005997.png (628×344)

附家具上傳的CelerFT

這個專案的程式碼可以再我的github資源庫上找到

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

如何使用Next.js(前端集成)構建多租戶SaaS應用程序如何使用Next.js(前端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript:探索網絡語言的多功能性JavaScript:探索網絡語言的多功能性Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的演變:當前的趨勢和未來前景JavaScript的演變:當前的趨勢和未來前景Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

神秘的JavaScript:它的作用以及為什麼重要神秘的JavaScript:它的作用以及為什麼重要Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python還是JavaScript更好?Python還是JavaScript更好?Apr 06, 2025 am 12:14 AM

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

如何安裝JavaScript?如何安裝JavaScript?Apr 05, 2025 am 12:16 AM

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境