Advertisement
Guest User

Untitled

a guest
Mar 24th, 2025
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.68 KB | None | 0 0
  1. Dockerfile:
  2. # Базовый образ для запуска
  3. FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
  4. WORKDIR /app
  5. EXPOSE 5000
  6.  
  7. # Образ для сборки
  8. FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
  9. WORKDIR /src
  10.  
  11. # Копируем файл проекта
  12. COPY DistributedSystems_Lab3.csproj ./
  13. RUN dotnet restore DistributedSystems_Lab3.csproj
  14.  
  15. # Копируем исходный код
  16. COPY . .
  17. RUN dotnet build DistributedSystems_Lab3.csproj -c Release -o /app/build
  18.  
  19. # Публикация
  20. FROM build AS publish
  21. RUN dotnet publish DistributedSystems_Lab3.csproj -c Release -o /app/publish /p:UseAppHost=false
  22.  
  23. # Финальный контейнер
  24. FROM base AS final
  25. WORKDIR /app
  26. COPY --from=publish /app/publish .
  27.  
  28. # Запуск
  29. CMD ["dotnet", "DistributedSystems_Lab3.dll"]
  30.  
  31. docker-compose.yml:
  32.  
  33. services:
  34. central:
  35. container_name: central
  36. image: myapp
  37. environment:
  38. - NodeRole=central
  39. - ASPNETCORE_URLS=http://+:5000
  40. ports:
  41. - "5000:5000"
  42. networks:
  43. - app_net
  44. deploy:
  45. restart_policy:
  46. condition: on-failure
  47.  
  48. worker1:
  49. container_name: worker1
  50. image: myapp
  51. environment:
  52. - NodeRole=worker
  53. - ASPNETCORE_URLS=http://+:5001
  54. networks:
  55. - app_net
  56. volumes:
  57. - worker1_storage:/app/storage
  58. deploy:
  59. restart_policy:
  60. condition: on-failure
  61.  
  62. worker2:
  63. container_name: worker2
  64. image: myapp
  65. environment:
  66. - NodeRole=worker
  67. - ASPNETCORE_URLS=http://+:5002
  68. networks:
  69. - app_net
  70. volumes:
  71. - worker2_storage:/app/storage
  72. deploy:
  73. restart_policy:
  74. condition: on-failure
  75.  
  76. worker3:
  77. container_name: worker3
  78. image: myapp
  79. environment:
  80. - NodeRole=worker
  81. - ASPNETCORE_URLS=http://+:5003
  82. networks:
  83. - app_net
  84. volumes:
  85. - worker3_storage:/app/storage
  86. deploy:
  87. restart_policy:
  88. condition: on-failure
  89.  
  90. networks:
  91. app_net:
  92. driver: bridge
  93.  
  94. volumes:
  95. worker1_storage:
  96. worker2_storage:
  97. worker3_storage:
  98.  
  99.  
  100.  
  101. index.html:
  102. <!DOCTYPE html>
  103. <html lang="ru">
  104. <head>
  105. <meta charset="UTF-8">
  106. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  107. <title>Файловая система</title>
  108. </head>
  109. <body>
  110. <h2>Загрузка файла</h2>
  111. <input type="file" id="fileInput">
  112. <button onclick="uploadFile()">Загрузить</button>
  113. <progress id="uploadProgress" value="0" max="100" style="display: none; width: 100%;"></progress>
  114. <p id="uploadStatus"></p>
  115.  
  116. <h2>Скачать файл</h2>
  117. <input type="text" id="fileName" placeholder="Имя файла">
  118. <button onclick="downloadFile()">Скачать</button>
  119. <p id="downloadStatus"></p>
  120.  
  121. <script>
  122. async function uploadFile() {
  123. let file = document.getElementById('fileInput').files[0];
  124. let progressBar = document.getElementById("uploadProgress");
  125. let statusText = document.getElementById("uploadStatus");
  126.  
  127. if (!file) {
  128. alert("Выберите файл");
  129. return;
  130. }
  131.  
  132. progressBar.style.display = "block";
  133. progressBar.value = 0;
  134. statusText.innerText = "Загрузка началась...";
  135.  
  136. let formData = new FormData();
  137. formData.append("file", file);
  138.  
  139. try {
  140. let response = await fetch('/api/file/save', {
  141. method: 'POST',
  142. body: formData
  143. });
  144.  
  145. if (!response.ok) {
  146. throw new Error(`Ошибка загрузки: ${response.statusText}`);
  147. }
  148.  
  149. let result = await response.text();
  150. alert(result);
  151. statusText.innerText = "Загрузка завершена!";
  152. } catch (error) {
  153. console.error("Ошибка загрузки:", error);
  154. alert("Ошибка загрузки файла.");
  155. statusText.innerText = "Ошибка загрузки!";
  156. } finally {
  157. progressBar.style.display = "none"; // Скрыть индикатор
  158. }
  159. }
  160.  
  161.  
  162. async function downloadFile() {
  163. let fileName = document.getElementById('fileName').value;
  164. if (!fileName) {
  165. alert("Введите имя файла");
  166. return;
  167. }
  168.  
  169. let response = await fetch(`/api/file/download/${fileName}`);
  170. if (response.status == 200) {
  171. let blob = await response.blob();
  172. let link = document.createElement("a");
  173. link.href = window.URL.createObjectURL(blob);
  174. link.download = fileName;
  175. document.body.appendChild(link);
  176. link.click();
  177. document.body.removeChild(link);
  178. } else {
  179. alert("Файл не найден");
  180. }
  181. }
  182. </script>
  183. </body>
  184. </html>
  185.  
  186.  
  187.  
  188.  
  189. CentralFileStorageService:
  190.  
  191. using Microsoft.AspNetCore.Mvc;
  192.  
  193. namespace DistributedSystems_Lab3
  194. {
  195. public class CentralFileStorageService
  196. {
  197. private readonly HttpClient _httpClient;
  198. private readonly List<string> _workerUrls = new()
  199. {
  200. "http://worker1:5001",
  201. "http://worker2:5002",
  202. "http://worker3:5003"
  203. };
  204.  
  205. public CentralFileStorageService(HttpClient httpClient)
  206. {
  207. _httpClient = httpClient;
  208. }
  209.  
  210. public async Task UploadFile(IFormFile file)
  211. {
  212. int partSize = 5 * 1024 * 1024; // 5 MB
  213. int index = 0;
  214. string filename = file.FileName;
  215. using var stream = file.OpenReadStream();
  216. var buffer = new byte[partSize];
  217.  
  218. while (true)
  219. {
  220. int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
  221. if (bytesRead == 0) break;
  222.  
  223. var worker = _workerUrls[index % _workerUrls.Count];
  224. using var content = new MultipartFormDataContent
  225. {
  226. { new ByteArrayContent(buffer, 0, bytesRead), "file", $"{filename}_part{index}" }
  227. };
  228. await _httpClient.PostAsync($"{worker}/api/worker/save", content);
  229. index++;
  230. }
  231. }
  232.  
  233. public async Task<FileResult?> DownloadFile(string filename)
  234. {
  235. List<byte[]> fileParts = new();
  236.  
  237. // Запрашиваем части у всех worker-ов
  238. for (int i = 0; i < _workerUrls.Count; i++)
  239. {
  240. string partName = $"{filename}_part{i}";
  241. foreach (var worker in _workerUrls)
  242. {
  243. try
  244. {
  245. HttpResponseMessage response = await _httpClient.GetAsync($"{worker}/api/storage/load/{partName}");
  246. if (response.IsSuccessStatusCode)
  247. {
  248. byte[] partData = await response.Content.ReadAsByteArrayAsync();
  249. fileParts.Add(partData);
  250. break; // Если часть найдена, не запрашиваем у других worker-ов
  251. }
  252. }
  253. catch (Exception ex)
  254. {
  255. Console.WriteLine($"Ошибка при загрузке части {partName}: {ex.Message}");
  256. }
  257. }
  258. }
  259.  
  260. if (fileParts.Count == 0)
  261. return null; // Файл не найден
  262.  
  263. // Объединяем части в один файл
  264. byte[] fullFile = fileParts.SelectMany(part => part).ToArray();
  265.  
  266. // Отправляем файл пользователю
  267. return new FileContentResult(fullFile, "application/octet-stream")
  268. {
  269. FileDownloadName = filename
  270. };
  271. }
  272.  
  273. }
  274. }
  275.  
  276.  
  277.  
  278.  
  279. WorkerFileStorageService:
  280.  
  281. using Microsoft.AspNetCore.Mvc;
  282.  
  283. namespace DistributedSystems_Lab3
  284. {
  285. public class WorkerFileStorageService
  286. {
  287. private readonly HttpClient _httpClient;
  288. private readonly string _storagePath = "/app/storage/";
  289.  
  290. public WorkerFileStorageService(HttpClient httpClient)
  291. {
  292. _httpClient = httpClient;
  293. }
  294.  
  295. // Метод загрузки файла на worker
  296. public async Task UploadFile(IFormFile file)
  297. {
  298. string path = Path.Combine(_storagePath, file.FileName);
  299. using var stream = new FileStream(path, FileMode.Create);
  300. await file.CopyToAsync(stream);
  301. }
  302.  
  303. // Метод для получения части файла
  304. public async Task<byte[]?> GetFilePart(string filename)
  305. {
  306. string path = Path.Combine(_storagePath, filename);
  307. if (!File.Exists(path))
  308. return null;
  309.  
  310. return await File.ReadAllBytesAsync(path);
  311. }
  312. }
  313. }
  314.  
  315.  
  316.  
  317.  
  318. FileController:
  319.  
  320. using Microsoft.AspNetCore.Mvc;
  321.  
  322. namespace DistributedSystems_Lab3
  323. {
  324. [Route("api/file")]
  325. [ApiController]
  326. public class FileController : ControllerBase
  327. {
  328. private readonly CentralFileStorageService _storageService;
  329.  
  330. public FileController(CentralFileStorageService storageService)
  331. {
  332. _storageService = storageService;
  333. }
  334.  
  335. [HttpPost("save")]
  336. public async Task<IActionResult> UploadFile([FromForm] IFormFile file)
  337. {
  338. if (file == null)
  339. return BadRequest("Файл не загружен");
  340.  
  341. await _storageService.UploadFile(file);
  342. return Ok($"Файл {file.FileName} загружен");
  343. }
  344.  
  345. [HttpGet("download/{filename}")]
  346. public async Task<IActionResult> DownloadFile(string filename)
  347. {
  348. var file = await _storageService.DownloadFile(filename);
  349. if (file == null)
  350. return NotFound("Файл не найден");
  351.  
  352. return file;
  353. }
  354. }
  355.  
  356. }
  357.  
  358.  
  359.  
  360.  
  361.  
  362. WorkerController:
  363.  
  364. using Microsoft.AspNetCore.Mvc;
  365.  
  366. namespace DistributedSystems_Lab3
  367. {
  368. [Route("api/worker")]
  369. [ApiController]
  370. public class WorkerController : ControllerBase
  371. {
  372. private readonly WorkerFileStorageService _workerStorage;
  373.  
  374. public WorkerController(WorkerFileStorageService workerStorage)
  375. {
  376. _workerStorage = workerStorage;
  377. }
  378.  
  379. //загрузка файла на воркеры через HTTP
  380. [HttpPost("save")]
  381. public async Task<IActionResult> SaveFile([FromForm] IFormFile file)
  382. {
  383. if (file == null)
  384. return BadRequest("Файл не загружен");
  385.  
  386. await _workerStorage.UploadFile(file);
  387. return Ok("Файл сохранен");
  388. }
  389.  
  390. //скачивание файла с воркера через HTTP
  391. [HttpGet("load/{filename}")]
  392. public async Task<IActionResult> LoadFile(string filename)
  393. {
  394. var filePart = await _workerStorage.GetFilePart(filename);
  395. if (filePart == null)
  396. return NotFound("Часть файла не найдена");
  397.  
  398. return File(filePart, "application/octet-stream", filename);
  399. }
  400. }
  401.  
  402. }
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409. Program.cs:
  410. using DistributedSystems_Lab3;
  411. using Microsoft.AspNetCore.Builder;
  412. using Microsoft.AspNetCore.Hosting;
  413. using Microsoft.AspNetCore.Http;
  414. using Microsoft.Extensions.DependencyInjection;
  415. using Microsoft.Extensions.Hosting;
  416. using Microsoft.Extensions.Logging;
  417. using System;
  418.  
  419. var builder = WebApplication.CreateBuilder(args);
  420.  
  421. string nodeRole = Environment.GetEnvironmentVariable("NodeRole") ?? "worker";
  422. Console.WriteLine($"Node Role: {nodeRole}");
  423.  
  424. builder.Services.AddMvc();
  425. builder.Services.AddControllers();
  426. builder.Services.AddSingleton<HttpClient>();
  427. // Условная регистрация сервисов в зависимости от роли узла
  428. if (nodeRole == "central")
  429. {
  430. builder.Services.AddSingleton<CentralFileStorageService>();
  431. }
  432. else
  433. {
  434. builder.Services.AddSingleton<WorkerFileStorageService>();
  435. }
  436. var app = builder.Build();
  437.  
  438. app.MapGet("/", () => Results.Redirect("/index.html"));
  439.  
  440. app.UseStaticFiles();
  441.  
  442. app.UseRouting();
  443. app.UseAuthorization();
  444. app.MapControllers();
  445.  
  446. app.Run();
  447.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement