Add: Test-Client

This commit is contained in:
Sakurai Ryota 2024-03-24 14:17:48 +09:00
parent c70d7501e9
commit 89d7d4592e
7 changed files with 212 additions and 7 deletions

View File

@ -62,6 +62,24 @@ public class FileController : Controller
} }
} }
[HttpGet]
public IActionResult ReadInfo(FileReadModel model) {
if (!ModelState.IsValid) {
return BadRequest();
}
try {
FileModel fileModel = this.database.Read(model.FileID);
if (fileModel is null) {
return NotFound();
}
return Json(fileModel);
} catch (Exception) {
return Problem();
}
}
[HttpGet] [HttpGet]
public IActionResult Read(FileReadModel model) { public IActionResult Read(FileReadModel model) {
if (!ModelState.IsValid) { if (!ModelState.IsValid) {
@ -84,4 +102,26 @@ public class FileController : Controller
return Problem(); return Problem();
} }
} }
[HttpPost]
public IActionResult Delete(FileDeleteModel model) {
if (!ModelState.IsValid) {
return BadRequest();
}
try {
FileModel fileModel = this.database.Read(model.FileID);
if (fileModel is null) {
return NotFound();
}
this.provider.DeleteFile(fileModel);
return Ok();
} catch (FileNotFoundException) {
return NotFound();
} catch (Exception) {
return Problem();
}
}
} }

View File

@ -23,22 +23,34 @@ public class StorageProvider {
} }
public async Task SaveFile(FileModel fileModel, FileStream fs) { public async Task SaveFile(FileModel fileModel, FileStream fs) {
string extension = Path.GetExtension(fileModel.FileName); string saveFullName = GetFullPath(fileModel);
string saveFileName = string.Format("{0}{1}", fileModel.FileID, extension);
string saveFullName = Path.Combine(this.saveDirectory, saveFileName);
using (FileStream dest = new FileStream(saveFullName, FileMode.OpenOrCreate)) { using (FileStream dest = new FileStream(saveFullName, FileMode.OpenOrCreate)) {
await fs.CopyToAsync(dest); await fs.CopyToAsync(dest);
} }
} }
public Stream GetFile(FileModel fileModel) { public Stream GetFile(FileModel fileModel) {
string extension = Path.GetExtension(fileModel.FileName); string saveFullName = GetFullPath(fileModel);
string saveFileName = string.Format("{0}{1}", fileModel.FileID, extension);
string saveFullName = Path.Combine(this.saveDirectory, saveFileName);
if (!File.Exists(saveFullName)) { if (!File.Exists(saveFullName)) {
throw new FileNotFoundException(); throw new FileNotFoundException();
} }
return new FileStream(saveFullName, FileMode.Open); return new FileStream(saveFullName, FileMode.Open);
} }
public void DeleteFile(FileModel fileModel) {
string saveFullName = GetFullPath(fileModel);
if (!File.Exists(saveFullName)) {
throw new FileNotFoundException();
}
File.Delete(saveFullName);
}
public string GetFullPath(FileModel fileModel) {
string extension = Path.GetExtension(fileModel.FileName);
string saveFileName = string.Format("{0}{1}", fileModel.FileID, extension);
string saveFullName = Path.Combine(this.saveDirectory, saveFileName);
return saveFullName;
}
} }

View File

@ -10,4 +10,5 @@ public class FileModel {
public string MimeType { get; set; } public string MimeType { get; set; }
public string HashValue { get; set; } public string HashValue { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public bool IsDeleted { get; set; } = false;
} }

View File

@ -0,0 +1,8 @@
using System.ComponentModel.DataAnnotations;
namespace StorageServer.Models.Request;
public class FileDeleteModel {
[Required]
public long FileID { get; set; }
}

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>disable</Nullable> <Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>

25
StorageServer.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StorageServer", "StorageServer.csproj", "{4BDA80C2-0B1E-4B29-993A-65572587066E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4BDA80C2-0B1E-4B29-993A-65572587066E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4BDA80C2-0B1E-4B29-993A-65572587066E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4BDA80C2-0B1E-4B29-993A-65572587066E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4BDA80C2-0B1E-4B29-993A-65572587066E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F6E3DEC7-59C2-46F8-949E-F523A72DE0AE}
EndGlobalSection
EndGlobal

119
test-client/index.html Normal file
View File

@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>StorageServer</title>
<link rel="stylesheet" href="https://devras.net/cloud/css/bootstrap.min.css" />
</head>
<body>
<div class="container">
<div class="m-2">
<form method="post" enctype="multipart/form-data" action="http://localhost:5000/File/Create" id="upload_form">
<div class="form-group row">
<div class="col-3">
<label for="file" class="form-label">アップロードするファイル</label>
</div>
<div class="col-9">
<input type="file" name="File" accept="*/*" id="file" class="form-control" multiple />
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">アップロード</button>
</div>
</form>
</div>
<div class="m-2">
<div class="row">
<div class="col-6">
<img src="" class="img-fluid" id="img" />
</div>
<div class="col-6">
<ul class="list-group" id="file_list"></ul>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', async () => {
const uploadForm = document.getElementById('upload_form');
const fileInput = document.getElementById('file');
const imageContainer = document.getElementById('img');
const fileList = document.getElementById('file_list');
const appendFile = (fileId, fileName) => {
const a = document.createElement('a');
a.href = `http://localhost:5000/File/Read/${fileId}`;
a.textContent = `${fileName}`;
const li = document.createElement('li');
li.classList.add('list-group-item');
li.append(a);
fileList.append(li);
return li;
};
const readFileList = async () => {
fileList.innerHTML = ``;
const response = await fetch('http://localhost:5000/FileList');
const json = await response.json();
for (const item of json)
{
const li = appendFile(item.fileID, item.fileName);
const a = li.querySelector('a');
if (item.mimeType.startsWith("image/"))
{
a.addEventListener('click', async e => {
e.preventDefault();
imageContainer.src = a.href;
});
}
}
};
const uploadRequest = async (file, fileName) => {
const fd = new FormData();
fd.append("File", file);
if (typeof fileName === "string" && fileName.length > 0) {
fd.append("FileName", fileName);
}
const response = await fetch("http://localhost:5000/File/Create", {
method: "POST",
body: fd,
}).catch(() => {
return {
ok: false,
};
});
if (!response.ok) {
return false;
}
return await response.json();
};
uploadForm.addEventListener('submit', async e => {
e.preventDefault();
if (fileInput.files.length === 0) {
return;
}
const promises = [];
for (let i = 0 ; i < fileInput.files.length ; i++) {
promises.push(uploadRequest(fileInput.files[i]));
}
await Promise.all(promises);
fileInput.value = ``;
await readFileList();
});
readFileList();
});
</script>
</body>
</html>