powershell编写一个简易的http服务器httpServer

devtools/2025/2/7 0:41:01/
http://www.w3.org/2000/svg" style="display: none;">

文章目录

    • powershell一键启动
      • 检查相关进程
    • 源码

powershell一键启动

一键启动脚本内容(powershell,兼容windows powershell和powershell7+)

irm https://gitee.com/xuchaoxin1375/scripts/raw/main/PS/Tools/Tools.psm1|iex
sleep 0.5
help Start-HTTPServer
#可以指定参数选择服务器根目录和端口
start-httpServer

一键启动依赖于互联网,会从gitee下载代码运行

如果要离线运行,参考最后一节,或者部署上述脚本仓库scripts: 实用脚本集合,以powershell模块为主(针对powershell 7开发) 支持一键部署,改善windows下的shell实用体验


如果部署相关仓库pwsh模块,可以使用Start-HttpserverBG来启动一个后台httpServer进程

可以配合一下方法查询相关进程

检查相关进程

@("*pwsh*","*powershell*")|%{ps -Name $_ } |?{$_.CommandLine -like '*httpServer*'}

例如:

@("*pwsh*","*powershell*")|%{ps -Name $_ } |?{$_.CommandLine -like '*httpServer*'}NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName------    -----      -----     ------      --  -- -----------84    45.52     116.32       1.91   12084   2 pwsh

杀死查询结果

ps -Id 12084 |kill

源码

可以跳过不看,如果源码不可用,则可以将下面代码拷贝到powershell的配置文件或者自动导入模块中,然后用powershell命令行收入Start-HttpServer也能离线(不联网)启动本地服务器

更直接的用法是将内容复制保存到一个.ps1脚本文件中,然后通过右键,选择以powershell方式运行(建议用pwsh而非自带的powershell.exe)即可启动服务

windows powershell.exe对于中文(utf8)编码的脚本可能会乱码报错,因此下面的代码纯英文

# If you need to set the service start path, modify the parameters on the last line.
# By default, the desktop is set as the server directory, and the port is 8080.function Format-FileSize
{param([long]$Size)if ($Size -gt 1GB) { return "{0:N2} GB" -f ($Size / 1GB) }if ($Size -gt 1MB) { return "{0:N2} MB" -f ($Size / 1MB) }if ($Size -gt 1KB) { return "{0:N2} KB" -f ($Size / 1KB) }return "$Size B"
}function Get-MimeType
{param([string]$Extension)$MimeTypes = @{".txt"  = "text/plain; charset=utf-8"".ps1"  = "text/plain; charset=utf-8"".py"   = "text/plain; charset=utf-8"".htm"  = "text/html; charset=utf-8"".html" = "text/html; charset=utf-8"".css"  = "text/css; charset=utf-8"".js"   = "text/javascript; charset=utf-8"".json" = "application/json; charset=utf-8"".jpg"  = "image/jpeg"".jpeg" = "image/jpeg"".png"  = "image/png"".gif"  = "image/gif"".pdf"  = "application/pdf"".xml"  = "application/xml; charset=utf-8"".zip"  = "application/zip"".md"   = "text/markdown; charset=utf-8"".mp4"  = "video/mp4"".mp3"  = "audio/mpeg"".wav"  = "audio/wav"}$key = $Extension.ToLower()if ($MimeTypes.ContainsKey($key)){return $MimeTypes[$key]}return "application/octet-stream"
}function Get-DirectoryListing
{param($RelativePath, $Items)$html = @"
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Index of /$RelativePath</title><style>body { font-family: Arial, sans-serif; margin: 20px; }table { border-collapse: collapse; width: 100%; }th, td { text-align: left; padding: 8px; border-bottom: 1px solid #ddd; }th { background-color: #f2f2f2; }tr:hover { background-color: #f5f5f5; }a { text-decoration: none; color: #0066cc; }.size { text-align: right; }.date { white-space: nowrap; }</style>
</head>
<body><h1>Index of /$RelativePath</h1><table><tr><th>Name</th><th class="size">Size</th><th class="date">Last Modified</th></tr>
"@if ($RelativePath){$html += "<tr><td><a href='../'>..</a></td><td></td><td></td></tr>"}# Process folders and files separately and sort by name$Folders = $Items | Where-Object { $_.PSIsContainer } | Sort-Object Name$Files = $Items | Where-Object { !$_.PSIsContainer } | Sort-Object Name# Display folders firstforeach ($Item in $Folders){$Name = $Item.Name$LastModified = $Item.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")$EncodedName = [System.Web.HttpUtility]::UrlEncode($Name)$html += "<tr><td><a href='$EncodedName/'>$Name/</a></td><td class='size'>-</td><td class='date'>$LastModified</td></tr>"}# Display files nextforeach ($Item in $Files){$Name = $Item.Name$Size = Format-FileSize $Item.Length$LastModified = $Item.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")$EncodedName = [System.Web.HttpUtility]::UrlEncode($Name)$html += "<tr><td><a href='$EncodedName'>$Name</a></td><td class='size'>$Size</td><td class='date'>$LastModified</td></tr>"}$html += @"</table><footer style="margin-top: 20px; color: #666; font-size: 12px;">Total $($Folders.Count) folders, $($Files.Count) files</footer>
</body>
</html>
"@return $html
}function Start-HTTPServer
{<#.SYNOPSISStarts a simple HTTP file server..DESCRIPTIONServes a specified local folder as the root directory of an HTTP server, defaulting to port 8080..PARAMETER PathSpecifies the local folder path to be used as the server root directory..PARAMETER PortSpecifies the port number the HTTP server should listen on, defaulting to 8080..EXAMPLEStart-HTTPServer -Path "C:\Share" -Port 8000Serves the C:\Share folder as root at port 8000..EXAMPLEStart-HTTPServerServes the current directory as root at port 8080.#>[CmdletBinding()]param([Parameter(Position = 0)][string]$Path = (Get-Location).Path,[Parameter(Position = 1)][int]$Port = 8080)Add-Type -AssemblyName System.Webtry{# Validate path existsif (-not (Test-Path $Path)){throw "The specified path '$Path' does not exist."}# Create HTTP listener$Listener = New-Object System.Net.HttpListener$Listener.Prefixes.Add("http://+:$Port/")# Try to start the listenertry{$Listener.Start()}catch{throw "Cannot start HTTP server, possibly due to insufficient permissions or port already in use: $_"}Write-Host "HTTP server has started:"Write-Host "Root directory: $Path"Write-Host "Address: http://localhost:$Port/"Write-Host "Press Ctrl+C to stop the server (it may take a few seconds, if you can't wait consider closing the corresponding command line window)"while ($Listener.IsListening){# Wait for request$Context = $Listener.GetContext()$Request = $Context.Request$Response = $Context.Response# URL decode request path$DecodedPath = [System.Web.HttpUtility]::UrlDecode($Request.Url.LocalPath)$LocalPath = Join-Path $Path $DecodedPath.TrimStart('/')# Set response header, support UTF-8$Response.Headers.Add("Content-Type", "text/html; charset=utf-8")# Handle directory requestif ((Test-Path $LocalPath) -and (Get-Item $LocalPath).PSIsContainer){$LocalPath = Join-Path $LocalPath "index.html"if (-not (Test-Path $LocalPath)){# Generate directory listing$Content = Get-DirectoryListing $DecodedPath.TrimStart('/') (Get-ChildItem (Join-Path $Path $DecodedPath.TrimStart('/')))$Buffer = [System.Text.Encoding]::UTF8.GetBytes($Content)$Response.ContentLength64 = $Buffer.Length$Response.OutputStream.Write($Buffer, 0, $Buffer.Length)$Response.Close()continue}}# Handle file requestif (Test-Path $LocalPath){$File = Get-Item $LocalPath$Response.ContentType = Get-MimeType $File.Extension$Response.ContentLength64 = $File.Length# Add filename encoding support$FileName = [System.Web.HttpUtility]::UrlEncode($File.Name)$Response.Headers.Add("Content-Disposition", "inline; filename*=UTF-8''$FileName")$FileStream = [System.IO.File]::OpenRead($File.FullName)$FileStream.CopyTo($Response.OutputStream)$FileStream.Close()}else{# Return 404$Response.StatusCode = 404$Content = "404 - File not found"$Buffer = [System.Text.Encoding]::UTF8.GetBytes($Content)$Response.ContentLength64 = $Buffer.Length$Response.OutputStream.Write($Buffer, 0, $Buffer.Length)}$Response.Close()}}finally{if ($Listener){$Listener.Stop()$Listener.Close()}}
}function Start-HTTPServerBG
{param (# Default shell is Windows PowerShell, if PowerShell 7+ (or pwsh) is installed, use pwsh instead;# By default, need to add Start-HTTPServer to PowerShell configuration file or PowerShell auto-import module, otherwise Start-HTTPServerBG command will not be available, leading to start failure.# $shell = "powershell",$shell = "pwsh", # Personally prefer pwsh$path = "$home\Desktop",$Port = 8080)Write-Verbose "Trying to start HTTP server..." -Verbose# $PSBoundParameters $params = [PSCustomObject]@{shell = $shellpath  = $pathPort  = $Port}Write-Output $params # Cannot directly output literal object with Write-Output, it will be treated as a string# Write-Output $shell, $path, $Port# $exp = "Start-Process -WindowStyle Hidden -FilePath $shell -ArgumentList { {c Start-HTTPServer -path $path -port $Port } -PassThru"# Write-Output $exp# $ps = $exp | Invoke-Expression# $func = ${Function:Start-HTTPServer} # Since the complete code of Start-HTTPServer is too scattered, just writing this way cannot obtain the complete Start-HTTPServer function$ps = Start-Process -FilePath $shell -ArgumentList "-c Start-HTTPServer -path $path -port $Port" -PassThru# Debug start-process syntax# $ps = Start-Process -FilePath pwsh -ArgumentList "-c", "Get-Location;Pause "return $ps}# Modify as needed
Start-HTTPServer -Path "$home\Desktop" -Port 8080

http://www.ppmy.cn/devtools/156660.html

相关文章

Rust场景示例:为什么要使用切片类型

通过对比 不用切片 和 使用切片 的场景&#xff0c;说明切片类型在 Rust 中的必要性&#xff1a; 场景&#xff1a;提取字符串中的单词 假设我们需要编写一个函数&#xff0c;从一个句子中提取第一个单词。我们将分别展示 不用切片 和 使用切片 的实现&#xff0c;并对比二者的…

单机性能调优中的程序优化

目录 一、系统框架的选择 二、程序优化 表单压缩 局部刷新 仅取所需 逻辑清晰 谨慎继承 程序算法优化 批处理 延迟加载 防止内存泄漏 减少大对象引用 防止争用死锁 存储过程 内存分配 并行 异步 缓存 单机优化顾名思义就是我们要在单机上对系统的性能进行调优…

8.PPT:小李-第二次世界大战【21】

目录 NO123 ​ NO4567 ​ NO8\9\10\11​ 图片→格式→大小对话框→锁定纵横比✔动画→飞入→效果选项&#xff1a;方向/序列→开始→持续时间→延迟时间持续时间&#xff1a;1s延迟&#xff1a;0.5s音频剪切时间&#xff1a;0.5s&#xff1a;00:00.500自动换片时间设置&…

javaEE初阶————多线程初阶(1)

多线程初阶———— 1&#xff0c;认识线程 1.1 概念 1&#xff09;线程是什么 线程就是一个“执行流”&#xff0c;可以理解为程序执行的最小单位&#xff1b; 可以看成轻量级的进程&#xff1b; 2&#xff09;为啥要有线程 “并发编程” 的需要&#xff0c;但是我们不…

pytorch图神经网络处理图结构数据

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 图神经网络&#xff08;Graph Neural Networks&#xff0c;GNNs&#xff09;是一类能够处理图结构数据的深度学习模型。图结构数据由节点&#xff08;vertices&#xff09;和边&#xff08;edges&#xff09;组成&a…

TCP连接管理与UDP协议IP协议与ethernet协议

SEO Meta Description: 深入解析TCP连接管理、UDP协议、IP协议与Ethernet协议的工作原理及其在网络通信中的应用&#xff0c;全面了解各协议的功能与区别。 介绍 网络通信依赖于一系列协议来确保数据的可靠传输和高效处理。本文将详细介绍TCP连接管理、UDP协议、IP协议和Ethe…

深入解析:如何获取商品 SKU 详细信息

在电商领域&#xff0c;SKU&#xff08;Stock Keeping Unit&#xff0c;库存进出计量的基本单元&#xff09;是商品管理中的一个重要概念。每个 SKU 都代表了一个具体的产品变体&#xff0c;例如不同的颜色、尺寸或配置。获取商品的 SKU 详细信息对于商家优化库存管理、提高运营…

ChatGPT怎么回事?

纯属发现&#xff0c;调侃一下~ 这段时间deepseek不是特别火吗&#xff0c;尤其是它的推理功能&#xff0c;突发奇想&#xff0c;想用deepseek回答一些问题&#xff0c;回答一个问题之后就回复服务器繁忙&#xff08;估计还在被攻击吧~_~&#xff09; 然后就转向了GPT&#xf…