add webhosting
This commit is contained in:
244
ArinWarev1/WebServer/Example_WebServer_Usage.vb
Normal file
244
ArinWarev1/WebServer/Example_WebServer_Usage.vb
Normal file
@@ -0,0 +1,244 @@
|
||||
' OWIN 정적 파일 호스팅 서버 사용 예제
|
||||
'
|
||||
' 이 파일은 StaticFileServer를 사용하는 방법을 보여줍니다.
|
||||
' 실제 사용 시에는 MdiMain.vb 또는 필요한 폼에서 사용하세요.
|
||||
|
||||
Imports Eco2Ar.WebServer
|
||||
Imports System.IO
|
||||
|
||||
Namespace Examples
|
||||
|
||||
''' <summary>
|
||||
''' 웹 서버 사용 예제
|
||||
''' </summary>
|
||||
Public Class WebServerExample
|
||||
|
||||
Private server As StaticFileServer
|
||||
|
||||
''' <summary>
|
||||
''' 예제 1: 기본 사용법
|
||||
''' </summary>
|
||||
Public Sub Example1_BasicUsage()
|
||||
' 1. 정적 파일을 서빙할 디렉토리 경로 설정
|
||||
Dim wwwrootPath As String = Path.Combine(Application.StartupPath, "wwwroot")
|
||||
|
||||
' 2. 서버 인스턴스 생성 (포트 58123 사용)
|
||||
server = New StaticFileServer(wwwrootPath, 58123)
|
||||
|
||||
' 3. 서버 시작
|
||||
server.Start()
|
||||
|
||||
' 4. 브라우저에서 열기 (선택사항)
|
||||
' server.OpenInBrowser()
|
||||
|
||||
MsgBox("웹 서버가 시작되었습니다." & vbCrLf & _
|
||||
"URL: " & server.BaseUrl & vbCrLf & _
|
||||
"루트 경로: " & server.RootPath, _
|
||||
MsgBoxStyle.Information, "웹 서버")
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 예제 2: MdiMain에서 사용 (프로그램 시작 시 서버 시작)
|
||||
''' </summary>
|
||||
Public Sub Example2_IntegrationWithMdiMain()
|
||||
' MdiMain.vb의 MdiMain_Load 이벤트에 추가:
|
||||
'
|
||||
' Private webServer As StaticFileServer
|
||||
'
|
||||
' Private Sub MdiMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
||||
' ' ... 기존 코드 ...
|
||||
'
|
||||
' Try
|
||||
' ' 웹 서버 초기화 및 시작
|
||||
' Dim wwwPath = Path.Combine(Application.StartupPath, "wwwroot")
|
||||
' webServer = New StaticFileServer(wwwPath)
|
||||
' webServer.Start()
|
||||
' Catch ex As Exception
|
||||
' ' 웹 서버 시작 실패해도 프로그램은 계속 실행
|
||||
' Debug.WriteLine("웹 서버 시작 실패: " & ex.Message)
|
||||
' End Try
|
||||
' End Sub
|
||||
'
|
||||
' Private Sub MdiMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
|
||||
' ' ... 기존 코드 ...
|
||||
'
|
||||
' ' 웹 서버 정리
|
||||
' If webServer IsNot Nothing Then
|
||||
' webServer.Stop()
|
||||
' webServer.Dispose()
|
||||
' End If
|
||||
' End Sub
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 예제 3: 특정 파일 브라우저에서 열기
|
||||
''' </summary>
|
||||
Public Sub Example3_OpenSpecificFile()
|
||||
If server Is Nothing OrElse Not server.IsRunning Then
|
||||
MsgBox("서버가 실행 중이 아닙니다.", MsgBoxStyle.Exclamation, "오류")
|
||||
Return
|
||||
End If
|
||||
|
||||
' 리포트 HTML 파일 열기
|
||||
server.OpenFileInBrowser("report.html")
|
||||
|
||||
' 또는 URL만 가져오기
|
||||
Dim reportUrl As String = server.GetFileUrl("reports/2025/report.html")
|
||||
MsgBox("리포트 URL: " & reportUrl, MsgBoxStyle.Information, "URL")
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 예제 4: 동적으로 HTML 파일 생성 후 표시
|
||||
''' </summary>
|
||||
Public Sub Example4_GenerateAndDisplay()
|
||||
If server Is Nothing OrElse Not server.IsRunning Then
|
||||
MsgBox("서버가 실행 중이 아닙니다.", MsgBoxStyle.Exclamation, "오류")
|
||||
Return
|
||||
End If
|
||||
|
||||
' HTML 파일 생성
|
||||
Dim htmlContent As String = "<!DOCTYPE html>" & vbCrLf & _
|
||||
"<html>" & vbCrLf & _
|
||||
"<head>" & vbCrLf & _
|
||||
" <meta charset=""utf-8"">" & vbCrLf & _
|
||||
" <title>ECO2 리포트</title>" & vbCrLf & _
|
||||
" <style>" & vbCrLf & _
|
||||
" body { font-family: 'Malgun Gothic', sans-serif; margin: 20px; }" & vbCrLf & _
|
||||
" h1 { color: #2c3e50; }" & vbCrLf & _
|
||||
" table { border-collapse: collapse; width: 100%; }" & vbCrLf & _
|
||||
" th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }" & vbCrLf & _
|
||||
" th { background-color: #4CAF50; color: white; }" & vbCrLf & _
|
||||
" </style>" & vbCrLf & _
|
||||
"</head>" & vbCrLf & _
|
||||
"<body>" & vbCrLf & _
|
||||
" <h1>건물 에너지 분석 리포트</h1>" & vbCrLf & _
|
||||
" <table>" & vbCrLf & _
|
||||
" <tr><th>항목</th><th>값</th></tr>" & vbCrLf & _
|
||||
" <tr><td>1차 에너지 소요량</td><td>123.45 kWh/m²·year</td></tr>" & vbCrLf & _
|
||||
" <tr><td>CO2 배출량</td><td>45.67 kg/m²·year</td></tr>" & vbCrLf & _
|
||||
" </table>" & vbCrLf & _
|
||||
"</body>" & vbCrLf & _
|
||||
"</html>"
|
||||
|
||||
' 파일 저장
|
||||
Dim reportPath As String = Path.Combine(server.RootPath, "report.html")
|
||||
File.WriteAllText(reportPath, htmlContent, System.Text.Encoding.UTF8)
|
||||
|
||||
' 브라우저에서 열기
|
||||
server.OpenFileInBrowser("report.html")
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 예제 5: 폼 버튼에서 웹 리포트 생성 및 표시
|
||||
''' </summary>
|
||||
Public Sub Example5_ButtonClick()
|
||||
' 폼의 버튼 클릭 이벤트에 추가:
|
||||
'
|
||||
' Private Sub btnShowWebReport_Click(sender As Object, e As EventArgs) Handles btnShowWebReport.Click
|
||||
' Try
|
||||
' ' 서버가 실행 중이 아니면 시작
|
||||
' If webServer Is Nothing OrElse Not webServer.IsRunning Then
|
||||
' Dim wwwPath = Path.Combine(Application.StartupPath, "wwwroot")
|
||||
' webServer = New StaticFileServer(wwwPath)
|
||||
' webServer.Start()
|
||||
' End If
|
||||
'
|
||||
' ' HTML 리포트 생성
|
||||
' GenerateHtmlReport()
|
||||
'
|
||||
' ' 브라우저에서 열기
|
||||
' webServer.OpenFileInBrowser("report.html")
|
||||
' Catch ex As Exception
|
||||
' MsgBox("리포트 생성 실패: " & ex.Message, MsgBoxStyle.Critical, "오류")
|
||||
' End Try
|
||||
' End Sub
|
||||
'
|
||||
' Private Sub GenerateHtmlReport()
|
||||
' ' 실제 데이터를 사용하여 HTML 생성
|
||||
' Dim html As String = BuildHtmlReport(DSET1, DSETR1, Result2)
|
||||
' Dim path As String = Path.Combine(webServer.RootPath, "report.html")
|
||||
' File.WriteAllText(path, html, System.Text.Encoding.UTF8)
|
||||
' End Sub
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 서버 중지
|
||||
''' </summary>
|
||||
Public Sub StopServer()
|
||||
If server IsNot Nothing Then
|
||||
server.Stop()
|
||||
server.Dispose()
|
||||
server = Nothing
|
||||
End If
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' 간단한 HTML 빌더 헬퍼 클래스
|
||||
''' </summary>
|
||||
Public Class HtmlReportBuilder
|
||||
|
||||
Private html As System.Text.StringBuilder
|
||||
|
||||
Public Sub New(title As String)
|
||||
html = New System.Text.StringBuilder()
|
||||
html.AppendLine("<!DOCTYPE html>")
|
||||
html.AppendLine("<html>")
|
||||
html.AppendLine("<head>")
|
||||
html.AppendLine(" <meta charset=""utf-8"">")
|
||||
html.AppendLine(" <title>" & title & "</title>")
|
||||
html.AppendLine(" <style>")
|
||||
html.AppendLine(" body { font-family: 'Malgun Gothic', sans-serif; margin: 20px; }")
|
||||
html.AppendLine(" h1 { color: #2c3e50; }")
|
||||
html.AppendLine(" h2 { color: #34495e; border-bottom: 2px solid #3498db; padding-bottom: 5px; }")
|
||||
html.AppendLine(" table { border-collapse: collapse; width: 100%; margin: 20px 0; }")
|
||||
html.AppendLine(" th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }")
|
||||
html.AppendLine(" th { background-color: #4CAF50; color: white; }")
|
||||
html.AppendLine(" tr:nth-child(even) { background-color: #f2f2f2; }")
|
||||
html.AppendLine(" .section { margin: 30px 0; }")
|
||||
html.AppendLine(" </style>")
|
||||
html.AppendLine("</head>")
|
||||
html.AppendLine("<body>")
|
||||
html.AppendLine(" <h1>" & title & "</h1>")
|
||||
End Sub
|
||||
|
||||
Public Sub AddSection(sectionTitle As String)
|
||||
html.AppendLine(" <div class=""section"">")
|
||||
html.AppendLine(" <h2>" & sectionTitle & "</h2>")
|
||||
End Sub
|
||||
|
||||
Public Sub StartTable(ParamArray headers As String())
|
||||
html.AppendLine(" <table>")
|
||||
html.Append(" <tr>")
|
||||
For Each headerItem As String In headers
|
||||
html.Append("<th>" & headerItem & "</th>")
|
||||
Next
|
||||
html.AppendLine("</tr>")
|
||||
End Sub
|
||||
|
||||
Public Sub AddRow(ParamArray cells As String())
|
||||
html.Append(" <tr>")
|
||||
For Each cellItem As String In cells
|
||||
html.Append("<td>" & cellItem & "</td>")
|
||||
Next
|
||||
html.AppendLine("</tr>")
|
||||
End Sub
|
||||
|
||||
Public Sub EndTable()
|
||||
html.AppendLine(" </table>")
|
||||
End Sub
|
||||
|
||||
Public Sub EndSection()
|
||||
html.AppendLine(" </div>")
|
||||
End Sub
|
||||
|
||||
Public Function Build() As String
|
||||
html.AppendLine("</body>")
|
||||
html.AppendLine("</html>")
|
||||
Return html.ToString()
|
||||
End Function
|
||||
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
50
ArinWarev1/WebServer/INSTALL.txt
Normal file
50
ArinWarev1/WebServer/INSTALL.txt
Normal file
@@ -0,0 +1,50 @@
|
||||
=====================================================
|
||||
OWIN 정적 파일 호스팅 서버 설치 가이드
|
||||
=====================================================
|
||||
|
||||
1. Visual Studio에서 ECO2_2025V1 프로젝트 열기
|
||||
|
||||
2. 메뉴: 도구 > NuGet 패키지 관리자 > 패키지 관리자 콘솔
|
||||
|
||||
3. 다음 명령들을 순서대로 실행:
|
||||
|
||||
Install-Package Owin -Version 1.0
|
||||
Install-Package Microsoft.Owin -Version 2.1.0
|
||||
Install-Package Microsoft.Owin.Host.HttpListener -Version 2.1.0
|
||||
Install-Package Microsoft.Owin.Hosting -Version 2.1.0
|
||||
Install-Package Microsoft.Owin.StaticFiles -Version 2.1.0
|
||||
|
||||
4. 프로젝트 다시 빌드
|
||||
|
||||
5. wwwroot 폴더 생성 (없는 경우):
|
||||
- 출력 디렉토리에 wwwroot 폴더 생성
|
||||
- Debug: ..\..\..\..\..\eco2\debug_2016\wwwroot
|
||||
- Release: c:\eco2\debug_2016\wwwroot
|
||||
|
||||
6. 기본 index.html 생성 (선택사항):
|
||||
wwwroot\index.html 파일에 다음 내용 추가:
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ECO2 Web Server</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>ECO2 웹 서버가 정상 작동 중입니다</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
7. 사용 예제는 Example_WebServer_Usage.vb 참고
|
||||
|
||||
8. 관리자 권한 필요 시 (선택사항):
|
||||
|
||||
관리자 권한 명령 프롬프트에서:
|
||||
netsh http add urlacl url=http://+:58123/ user=Everyone
|
||||
|
||||
=====================================================
|
||||
문제 발생 시:
|
||||
- README.md의 "문제 해결" 섹션 참고
|
||||
- 패키지 버전이 정확한지 확인 (2.1.0)
|
||||
- .NET Framework 4.0 타겟이 맞는지 확인
|
||||
=====================================================
|
||||
126
ArinWarev1/WebServer/MANUAL_INSTALL.md
Normal file
126
ArinWarev1/WebServer/MANUAL_INSTALL.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Visual Studio 2010 수동 설치 가이드
|
||||
|
||||
VS2010에는 NuGet이 기본 내장되어 있지 않으므로, 두 가지 방법 중 선택할 수 있습니다.
|
||||
|
||||
## 방법 1: NuGet Extension 설치 (권장)
|
||||
|
||||
1. Visual Studio 2010 열기
|
||||
2. **도구** > **확장 관리자** 클릭
|
||||
3. **온라인 갤러리** 선택
|
||||
4. 검색창에 "NuGet Package Manager" 입력
|
||||
5. **NuGet Package Manager** 찾아서 **다운로드** 클릭
|
||||
6. 설치 후 Visual Studio 재시작
|
||||
7. 이후 README.md의 NuGet 설치 방법 따라하기
|
||||
|
||||
또는 직접 다운로드:
|
||||
https://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c
|
||||
|
||||
## 방법 2: DLL 수동 추가 (NuGet 없이)
|
||||
|
||||
### 1단계: 필요한 DLL 다운로드
|
||||
|
||||
다음 NuGet 패키지를 직접 다운로드:
|
||||
|
||||
**다운로드 링크:**
|
||||
- https://www.nuget.org/packages/Owin/1.0
|
||||
- https://www.nuget.org/packages/Microsoft.Owin/2.1.0
|
||||
- https://www.nuget.org/packages/Microsoft.Owin.Host.HttpListener/2.1.0
|
||||
- https://www.nuget.org/packages/Microsoft.Owin.Hosting/2.1.0
|
||||
- https://www.nuget.org/packages/Microsoft.Owin.StaticFiles/2.1.0
|
||||
- https://www.nuget.org/packages/Microsoft.Owin.FileSystems/2.1.0
|
||||
|
||||
각 페이지에서 "Download package" 클릭
|
||||
|
||||
### 2단계: NuGet 패키지에서 DLL 추출
|
||||
|
||||
1. 다운로드한 `.nupkg` 파일의 확장자를 `.zip`으로 변경
|
||||
2. 압축 해제
|
||||
3. `lib\net40\` 폴더에서 DLL 파일 찾기
|
||||
4. 프로젝트 폴더에 `lib` 디렉토리 생성
|
||||
5. 모든 DLL을 `S:\Source\KICT\ECO2\lib\` 폴더에 복사
|
||||
|
||||
**필요한 DLL 목록:**
|
||||
- Owin.dll
|
||||
- Microsoft.Owin.dll
|
||||
- Microsoft.Owin.Host.HttpListener.dll
|
||||
- Microsoft.Owin.Hosting.dll
|
||||
- Microsoft.Owin.StaticFiles.dll
|
||||
- Microsoft.Owin.FileSystems.dll
|
||||
|
||||
### 3단계: Visual Studio 프로젝트에 참조 추가
|
||||
|
||||
1. 솔루션 탐색기에서 **ECO2_2025V1** 프로젝트 선택
|
||||
2. **참조** 폴더 우클릭 > **참조 추가**
|
||||
3. **찾아보기** 탭 선택
|
||||
4. `S:\Source\KICT\ECO2\lib\` 폴더로 이동
|
||||
5. 위의 모든 DLL 선택하여 추가
|
||||
|
||||
### 4단계: app.config에 바인딩 리디렉션 추가
|
||||
|
||||
`ArinWarev1\app.config` 파일을 열고 `</configuration>` 바로 앞에 추가:
|
||||
|
||||
```xml
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
```
|
||||
|
||||
## 방법 3: 스크립트로 자동 다운로드 (PowerShell)
|
||||
|
||||
프로젝트 루트에서 PowerShell 실행:
|
||||
|
||||
```powershell
|
||||
# lib 폴더 생성
|
||||
New-Item -ItemType Directory -Force -Path "lib"
|
||||
|
||||
# NuGet.exe 다운로드
|
||||
Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/v2.8.6/nuget.exe" -OutFile "nuget.exe"
|
||||
|
||||
# 패키지 다운로드
|
||||
.\nuget.exe install Owin -Version 1.0 -OutputDirectory packages
|
||||
.\nuget.exe install Microsoft.Owin -Version 2.1.0 -OutputDirectory packages
|
||||
.\nuget.exe install Microsoft.Owin.Host.HttpListener -Version 2.1.0 -OutputDirectory packages
|
||||
.\nuget.exe install Microsoft.Owin.Hosting -Version 2.1.0 -OutputDirectory packages
|
||||
.\nuget.exe install Microsoft.Owin.StaticFiles -Version 2.1.0 -OutputDirectory packages
|
||||
|
||||
# DLL 복사
|
||||
Copy-Item "packages\Owin.1.0\lib\net40\Owin.dll" -Destination "lib\"
|
||||
Copy-Item "packages\Microsoft.Owin.2.1.0\lib\net40\Microsoft.Owin.dll" -Destination "lib\"
|
||||
Copy-Item "packages\Microsoft.Owin.Host.HttpListener.2.1.0\lib\net40\Microsoft.Owin.Host.HttpListener.dll" -Destination "lib\"
|
||||
Copy-Item "packages\Microsoft.Owin.Hosting.2.1.0\lib\net40\Microsoft.Owin.Hosting.dll" -Destination "lib\"
|
||||
Copy-Item "packages\Microsoft.Owin.StaticFiles.2.1.0\lib\net40\Microsoft.Owin.StaticFiles.dll" -Destination "lib\"
|
||||
Copy-Item "packages\Microsoft.Owin.FileSystems.2.1.0\lib\net40\Microsoft.Owin.FileSystems.dll" -Destination "lib\"
|
||||
|
||||
Write-Host "DLL 다운로드 완료! lib 폴더를 확인하세요."
|
||||
```
|
||||
|
||||
## 방법 4: 미리 준비된 DLL 사용
|
||||
|
||||
팀원에게 이미 설치된 환경에서 다음 폴더의 DLL을 복사 받기:
|
||||
- `packages\Owin.1.0\lib\net40\`
|
||||
- `packages\Microsoft.Owin.2.1.0\lib\net40\`
|
||||
- `packages\Microsoft.Owin.Host.HttpListener.2.1.0\lib\net40\`
|
||||
- `packages\Microsoft.Owin.Hosting.2.1.0\lib\net40\`
|
||||
- `packages\Microsoft.Owin.StaticFiles.2.1.0\lib\net40\`
|
||||
- `packages\Microsoft.Owin.FileSystems.2.1.0\lib\net40\`
|
||||
|
||||
## 확인 방법
|
||||
|
||||
프로젝트를 빌드했을 때 다음 오류가 없으면 성공:
|
||||
- "형식 또는 네임스페이스 이름 'Owin'을 찾을 수 없습니다"
|
||||
- "형식 또는 네임스페이스 이름 'Microsoft'을 찾을 수 없습니다"
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### "Could not load file or assembly" 오류
|
||||
- app.config에 바인딩 리디렉션 추가했는지 확인
|
||||
- DLL 버전이 2.1.0이 맞는지 확인 (2.x 버전만 .NET 4.0 호환)
|
||||
|
||||
### "파일을 찾을 수 없습니다" 오류
|
||||
- 출력 디렉토리에 DLL이 복사되는지 확인
|
||||
- 참조의 "로컬 복사" 속성이 True인지 확인
|
||||
190
ArinWarev1/WebServer/README.md
Normal file
190
ArinWarev1/WebServer/README.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# OWIN 정적 파일 호스팅 서버
|
||||
|
||||
ECO2 프로젝트에 OWIN 기반 내장 웹 서버를 추가하여 HTML 리포트 및 정적 파일을 호스팅할 수 있습니다.
|
||||
|
||||
## 설치 방법
|
||||
|
||||
### 1. NuGet 패키지 설치
|
||||
|
||||
Visual Studio에서 Package Manager Console을 열고 다음 명령을 실행하세요:
|
||||
|
||||
```powershell
|
||||
# ECO2_2025V1 프로젝트를 기본 프로젝트로 선택 후 실행
|
||||
|
||||
Install-Package Microsoft.Owin -Version 2.1.0
|
||||
Install-Package Microsoft.Owin.Host.HttpListener -Version 2.1.0
|
||||
Install-Package Microsoft.Owin.Hosting -Version 2.1.0
|
||||
Install-Package Microsoft.Owin.StaticFiles -Version 2.1.0
|
||||
Install-Package Owin -Version 1.0
|
||||
```
|
||||
|
||||
또는 패키지 관리자 UI에서 다음 패키지를 검색하여 설치:
|
||||
- Microsoft.Owin (2.1.0)
|
||||
- Microsoft.Owin.Host.HttpListener (2.1.0)
|
||||
- Microsoft.Owin.Hosting (2.1.0)
|
||||
- Microsoft.Owin.StaticFiles (2.1.0)
|
||||
- Owin (1.0)
|
||||
|
||||
### 2. 프로젝트에 파일 추가
|
||||
|
||||
다음 파일들이 `WebServer` 폴더에 추가되었습니다:
|
||||
- `StaticFileServer.vb` - 메인 서버 클래스
|
||||
- `Startup.vb` - OWIN 시작 구성
|
||||
- `Example_WebServer_Usage.vb` - 사용 예제
|
||||
|
||||
Visual Studio에서 프로젝트를 다시 로드하면 자동으로 인식됩니다.
|
||||
|
||||
## 사용 방법
|
||||
|
||||
### 기본 사용법
|
||||
|
||||
```vb
|
||||
Imports Eco2Ar.WebServer
|
||||
Imports System.IO
|
||||
|
||||
' 1. 서버 인스턴스 생성
|
||||
Dim wwwrootPath As String = Path.Combine(Application.StartupPath, "wwwroot")
|
||||
Dim server As New StaticFileServer(wwwrootPath, 58123)
|
||||
|
||||
' 2. 서버 시작
|
||||
server.Start()
|
||||
|
||||
' 3. 브라우저에서 열기
|
||||
server.OpenInBrowser()
|
||||
|
||||
' 4. 사용 후 서버 중지
|
||||
server.Stop()
|
||||
```
|
||||
|
||||
### MdiMain에 통합
|
||||
|
||||
`MdiMain.vb`에 다음 코드를 추가:
|
||||
|
||||
```vb
|
||||
Public Class MdiMain
|
||||
Private webServer As StaticFileServer
|
||||
|
||||
Private Sub MdiMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
|
||||
' ... 기존 코드 ...
|
||||
|
||||
' 웹 서버 시작
|
||||
Try
|
||||
Dim wwwPath = Path.Combine(Application.StartupPath, "wwwroot")
|
||||
webServer = New StaticFileServer(wwwPath)
|
||||
webServer.Start()
|
||||
Catch ex As Exception
|
||||
Debug.WriteLine("웹 서버 시작 실패: " & ex.Message)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Sub MdiMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
|
||||
' ... 기존 코드 ...
|
||||
|
||||
' 웹 서버 정리
|
||||
If webServer IsNot Nothing Then
|
||||
webServer.Stop()
|
||||
webServer.Dispose()
|
||||
End If
|
||||
End Sub
|
||||
End Class
|
||||
```
|
||||
|
||||
### HTML 리포트 생성 및 표시
|
||||
|
||||
```vb
|
||||
' HTML 리포트 빌더 사용
|
||||
Dim builder As New HtmlReportBuilder("건물 에너지 분석 리포트")
|
||||
|
||||
builder.AddSection("1차 에너지 소요량")
|
||||
builder.StartTable("항목", "값", "단위")
|
||||
builder.AddRow("난방", "123.45", "kWh/m²·year")
|
||||
builder.AddRow("냉방", "67.89", "kWh/m²·year")
|
||||
builder.EndTable()
|
||||
builder.EndSection()
|
||||
|
||||
Dim html As String = builder.Build()
|
||||
|
||||
' 파일 저장
|
||||
Dim reportPath As String = Path.Combine(webServer.RootPath, "report.html")
|
||||
File.WriteAllText(reportPath, html, System.Text.Encoding.UTF8)
|
||||
|
||||
' 브라우저에서 열기
|
||||
webServer.OpenFileInBrowser("report.html")
|
||||
```
|
||||
|
||||
## 폴더 구조
|
||||
|
||||
```
|
||||
C:\eco2\debug_2016\
|
||||
├─ Eco2Ar.exe
|
||||
└─ wwwroot\ # 정적 파일 루트 디렉토리
|
||||
├─ index.html # 기본 페이지
|
||||
├─ report.html # 생성된 리포트
|
||||
├─ css\
|
||||
│ └─ styles.css
|
||||
├─ js\
|
||||
│ └─ scripts.js
|
||||
└─ images\
|
||||
└─ logo.png
|
||||
```
|
||||
|
||||
## 주요 기능
|
||||
|
||||
### StaticFileServer 클래스
|
||||
|
||||
- **Start()** - 웹 서버 시작
|
||||
- **Stop()** - 웹 서버 중지
|
||||
- **OpenInBrowser()** - 기본 브라우저에서 루트 URL 열기
|
||||
- **OpenFileInBrowser(relativePath)** - 특정 파일을 브라우저에서 열기
|
||||
- **GetFileUrl(relativePath)** - 파일의 전체 URL 반환
|
||||
- **IsRunning** - 서버 실행 상태 확인
|
||||
- **BaseUrl** - 서버 URL (http://localhost:58123)
|
||||
- **RootPath** - 정적 파일 루트 경로
|
||||
|
||||
### HtmlReportBuilder 클래스
|
||||
|
||||
간단한 HTML 리포트를 코드로 생성할 수 있는 헬퍼 클래스입니다.
|
||||
|
||||
## 포트 정보
|
||||
|
||||
- **기본 포트**: 58123 (일반적으로 사용하지 않는 포트)
|
||||
- 필요 시 생성자에서 다른 포트 지정 가능: `New StaticFileServer(path, 9999)`
|
||||
|
||||
## 보안 주의사항
|
||||
|
||||
- 이 웹 서버는 **localhost**에서만 접근 가능합니다 (외부 접근 불가)
|
||||
- 민감한 정보를 wwwroot에 저장하지 마세요
|
||||
- 필요한 경우에만 서버를 실행하고 사용 후 중지하세요
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### "포트가 이미 사용 중입니다" 오류
|
||||
|
||||
다른 프로그램이 58123 포트를 사용 중일 수 있습니다. 다른 포트를 사용하세요:
|
||||
|
||||
```vb
|
||||
Dim server As New StaticFileServer(wwwrootPath, 58124)
|
||||
```
|
||||
|
||||
### "관리자 권한이 필요합니다" 오류
|
||||
|
||||
일부 환경에서는 HTTP.sys 리스너 등록에 관리자 권한이 필요할 수 있습니다.
|
||||
다음 명령을 관리자 권한 명령 프롬프트에서 실행:
|
||||
|
||||
```cmd
|
||||
netsh http add urlacl url=http://+:58123/ user=Everyone
|
||||
```
|
||||
|
||||
### 패키지 설치 오류
|
||||
|
||||
.NET Framework 4.0 타겟 프로젝트이므로 반드시 2.x 버전의 OWIN 패키지를 사용해야 합니다.
|
||||
최신 버전(4.x)은 .NET Framework 4.5 이상이 필요합니다.
|
||||
|
||||
## 예제 코드 위치
|
||||
|
||||
더 자세한 사용 예제는 `Example_WebServer_Usage.vb` 파일을 참고하세요.
|
||||
|
||||
## 참고 자료
|
||||
|
||||
- [OWIN 공식 문서](http://owin.org/)
|
||||
- [Microsoft.Owin 문서](https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/)
|
||||
93
ArinWarev1/WebServer/Startup.vb
Normal file
93
ArinWarev1/WebServer/Startup.vb
Normal file
@@ -0,0 +1,93 @@
|
||||
' OWIN Startup 클래스
|
||||
Imports Owin
|
||||
Imports Microsoft.Owin.StaticFiles
|
||||
Imports Microsoft.Owin.FileSystems
|
||||
|
||||
Namespace WebServer
|
||||
|
||||
''' <summary>
|
||||
''' OWIN 시작 구성 클래스
|
||||
''' </summary>
|
||||
Public Class Startup
|
||||
|
||||
' 정적 필드로 RootPath 저장
|
||||
Public Shared RootPath As String = String.Empty
|
||||
|
||||
''' <summary>
|
||||
''' OWIN 미들웨어 구성
|
||||
''' </summary>
|
||||
''' <param name="app">App builder</param>
|
||||
Public Sub Configuration(app As IAppBuilder)
|
||||
' 루트 경로 확인
|
||||
If String.IsNullOrEmpty(RootPath) Then
|
||||
RootPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot")
|
||||
End If
|
||||
|
||||
' 정적 파일 서빙을 위한 파일 시스템 설정
|
||||
Dim fileSystem = New PhysicalFileSystem(RootPath)
|
||||
|
||||
' 정적 파일 옵션 설정
|
||||
Dim options As New FileServerOptions() With {
|
||||
.RequestPath = New Microsoft.Owin.PathString(""),
|
||||
.FileSystem = fileSystem,
|
||||
.EnableDirectoryBrowsing = False
|
||||
}
|
||||
|
||||
' MIME 타입 매핑 추가 (필요한 경우)
|
||||
options.StaticFileOptions.ContentTypeProvider = New CustomContentTypeProvider()
|
||||
|
||||
' 정적 파일 미들웨어 사용
|
||||
app.UseFileServer(options)
|
||||
|
||||
' 기본 핸들러 (루트 경로 접근 시)
|
||||
app.Run(Function(context)
|
||||
' 루트 경로 접근 시 index.html로 리다이렉트
|
||||
If context.Request.Path.Value = "/" OrElse context.Request.Path.Value = "" Then
|
||||
Dim indexPath = System.IO.Path.Combine(RootPath, "index.html")
|
||||
If System.IO.File.Exists(indexPath) Then
|
||||
context.Response.Redirect("/index.html")
|
||||
Else
|
||||
context.Response.StatusCode = 200
|
||||
context.Response.ContentType = "text/html"
|
||||
Dim tcs = New System.Threading.Tasks.TaskCompletionSource(Of Integer)()
|
||||
context.Response.WriteAsync("<html><body><h1>ECO2 Web Server</h1><p>서버가 정상적으로 실행 중입니다.</p><p>루트 경로: " & RootPath & "</p></body></html>")
|
||||
tcs.SetResult(0)
|
||||
Return tcs.Task
|
||||
End If
|
||||
End If
|
||||
Dim tcs2 = New System.Threading.Tasks.TaskCompletionSource(Of Integer)()
|
||||
tcs2.SetResult(0)
|
||||
Return tcs2.Task
|
||||
End Function)
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' 커스텀 Content Type Provider
|
||||
''' </summary>
|
||||
Public Class CustomContentTypeProvider
|
||||
Inherits Microsoft.Owin.StaticFiles.ContentTypes.FileExtensionContentTypeProvider
|
||||
|
||||
Public Sub New()
|
||||
MyBase.New()
|
||||
|
||||
' 추가 MIME 타입 매핑 (필요한 경우)
|
||||
' 기본적으로 일반적인 타입들은 이미 포함되어 있음
|
||||
If Not Me.Mappings.ContainsKey(".json") Then
|
||||
Me.Mappings.Add(".json", "application/json")
|
||||
End If
|
||||
If Not Me.Mappings.ContainsKey(".svg") Then
|
||||
Me.Mappings.Add(".svg", "image/svg+xml")
|
||||
End If
|
||||
If Not Me.Mappings.ContainsKey(".woff") Then
|
||||
Me.Mappings.Add(".woff", "font/woff")
|
||||
End If
|
||||
If Not Me.Mappings.ContainsKey(".woff2") Then
|
||||
Me.Mappings.Add(".woff2", "font/woff2")
|
||||
End If
|
||||
End Sub
|
||||
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
175
ArinWarev1/WebServer/StaticFileServer.vb
Normal file
175
ArinWarev1/WebServer/StaticFileServer.vb
Normal file
@@ -0,0 +1,175 @@
|
||||
' OWIN 기반 정적 파일 호스팅 서버
|
||||
'
|
||||
' 사용 방법:
|
||||
' Dim server As New StaticFileServer("C:\wwwroot", 58123)
|
||||
' server.Start()
|
||||
' ... 프로그램 실행 ...
|
||||
' server.Stop()
|
||||
|
||||
Imports System
|
||||
Imports System.IO
|
||||
Imports Microsoft.Owin.Hosting
|
||||
|
||||
Namespace WebServer
|
||||
|
||||
''' <summary>
|
||||
''' OWIN 기반 정적 파일 호스팅 서버
|
||||
''' 포트 58123 사용 (일반적으로 사용하지 않는 포트)
|
||||
''' </summary>
|
||||
Public Class StaticFileServer
|
||||
Implements IDisposable
|
||||
|
||||
Private _webApp As IDisposable
|
||||
Private _baseUrl As String
|
||||
Private _rootPath As String
|
||||
Private _isRunning As Boolean = False
|
||||
|
||||
''' <summary>
|
||||
''' 서버가 실행 중인지 여부
|
||||
''' </summary>
|
||||
Public ReadOnly Property IsRunning As Boolean
|
||||
Get
|
||||
Return _isRunning
|
||||
End Get
|
||||
End Property
|
||||
|
||||
''' <summary>
|
||||
''' 서버 URL (예: http://localhost:58123)
|
||||
''' </summary>
|
||||
Public ReadOnly Property BaseUrl As String
|
||||
Get
|
||||
Return _baseUrl
|
||||
End Get
|
||||
End Property
|
||||
|
||||
''' <summary>
|
||||
''' 정적 파일 루트 경로
|
||||
''' </summary>
|
||||
Public ReadOnly Property RootPath As String
|
||||
Get
|
||||
Return _rootPath
|
||||
End Get
|
||||
End Property
|
||||
|
||||
''' <summary>
|
||||
''' StaticFileServer 생성자
|
||||
''' </summary>
|
||||
''' <param name="rootPath">정적 파일을 서빙할 루트 디렉토리 경로</param>
|
||||
''' <param name="port">사용할 포트 번호 (기본값: 58123)</param>
|
||||
Public Sub New(rootPath As String, Optional port As Integer = 58123)
|
||||
If String.IsNullOrEmpty(rootPath) Then
|
||||
Throw New ArgumentException("rootPath는 비어있을 수 없습니다.", "rootPath")
|
||||
End If
|
||||
|
||||
If Not Directory.Exists(rootPath) Then
|
||||
Directory.CreateDirectory(rootPath)
|
||||
End If
|
||||
|
||||
_rootPath = Path.GetFullPath(rootPath)
|
||||
_baseUrl = String.Format("http://localhost:{0}", port)
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 웹 서버 시작
|
||||
''' </summary>
|
||||
Public Sub Start()
|
||||
If _isRunning Then
|
||||
Throw New InvalidOperationException("서버가 이미 실행 중입니다.")
|
||||
End If
|
||||
|
||||
Try
|
||||
' OWIN 서버 시작
|
||||
_webApp = WebApp.Start(Of Startup)(_baseUrl)
|
||||
_isRunning = True
|
||||
|
||||
' 루트 경로를 Startup에서 접근할 수 있도록 설정
|
||||
Startup.RootPath = _rootPath
|
||||
|
||||
Console.WriteLine("웹 서버 시작: {0}", _baseUrl)
|
||||
Console.WriteLine("루트 경로: {0}", _rootPath)
|
||||
Catch ex As Exception
|
||||
_isRunning = False
|
||||
Throw New Exception("웹 서버 시작 실패: " & ex.Message, ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 웹 서버 중지
|
||||
''' </summary>
|
||||
Public Sub [Stop]()
|
||||
If Not _isRunning Then
|
||||
Return
|
||||
End If
|
||||
|
||||
Try
|
||||
If _webApp IsNot Nothing Then
|
||||
_webApp.Dispose()
|
||||
_webApp = Nothing
|
||||
End If
|
||||
_isRunning = False
|
||||
Console.WriteLine("웹 서버 중지됨")
|
||||
Catch ex As Exception
|
||||
Throw New Exception("웹 서버 중지 실패: " & ex.Message, ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 리소스 해제
|
||||
''' </summary>
|
||||
Public Sub Dispose() Implements IDisposable.Dispose
|
||||
[Stop]()
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 특정 파일의 전체 URL 반환
|
||||
''' </summary>
|
||||
''' <param name="relativePath">상대 경로 (예: "index.html" 또는 "images/logo.png")</param>
|
||||
''' <returns>전체 URL</returns>
|
||||
Public Function GetFileUrl(relativePath As String) As String
|
||||
If String.IsNullOrEmpty(relativePath) Then
|
||||
Return _baseUrl & "/"
|
||||
End If
|
||||
|
||||
' 경로 정규화
|
||||
Dim normalizedPath As String = relativePath.Replace("\", "/")
|
||||
If Not normalizedPath.StartsWith("/") Then
|
||||
normalizedPath = "/" & normalizedPath
|
||||
End If
|
||||
|
||||
Return _baseUrl & normalizedPath
|
||||
End Function
|
||||
|
||||
''' <summary>
|
||||
''' 브라우저에서 루트 URL 열기
|
||||
''' </summary>
|
||||
Public Sub OpenInBrowser()
|
||||
If Not _isRunning Then
|
||||
Throw New InvalidOperationException("서버가 실행 중이 아닙니다.")
|
||||
End If
|
||||
|
||||
Try
|
||||
System.Diagnostics.Process.Start(_baseUrl)
|
||||
Catch ex As Exception
|
||||
Throw New Exception("브라우저 열기 실패: " & ex.Message, ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
''' 특정 파일을 브라우저에서 열기
|
||||
''' </summary>
|
||||
''' <param name="relativePath">상대 경로</param>
|
||||
Public Sub OpenFileInBrowser(relativePath As String)
|
||||
If Not _isRunning Then
|
||||
Throw New InvalidOperationException("서버가 실행 중이 아닙니다.")
|
||||
End If
|
||||
|
||||
Try
|
||||
Dim url As String = GetFileUrl(relativePath)
|
||||
System.Diagnostics.Process.Start(url)
|
||||
Catch ex As Exception
|
||||
Throw New Exception("브라우저 열기 실패: " & ex.Message, ex)
|
||||
End Try
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
Reference in New Issue
Block a user