Skip to content

Commit c74b000

Browse files
committed
feat: Enhance response display for file downloads and add file upload functionality
- Updated responseDisplayHandler.js to handle file download responses, including UI updates for download success messages and re-download functionality. - Added formatFileSize utility function to format file sizes in a human-readable format. - Modified swagger.json to reflect changes in API structure, including new endpoints for article management and file operations. - Implemented FileController in C# to handle file uploads and downloads, providing appropriate responses and error handling.
1 parent 5aad5e6 commit c74b000

File tree

16 files changed

+1689
-1409
lines changed

16 files changed

+1689
-1409
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using System.Text;
3+
4+
namespace JakubKozera.OpenApiUi.Sample.Controllers;
5+
6+
/// <summary>
7+
/// Controller for file operations
8+
/// </summary>
9+
[ApiController]
10+
[Route("api/[controller]")]
11+
[Produces("application/json")]
12+
public class FileController : ControllerBase
13+
{
14+
/// <summary>
15+
/// Uploads a file and returns its name and size
16+
/// </summary>
17+
/// <param name="file">The file to upload</param>
18+
/// <returns>File information including name and size</returns>
19+
/// <response code="200">Returns file information</response>
20+
/// <response code="400">No file provided or file is empty</response>
21+
[HttpPost("upload")]
22+
[ProducesResponseType<FileInfoResponse>(StatusCodes.Status200OK)]
23+
[ProducesResponseType<ProblemDetails>(StatusCodes.Status400BadRequest)]
24+
[Consumes("multipart/form-data")]
25+
public async Task<IActionResult> UploadFile(IFormFile file)
26+
{
27+
if (file == null || file.Length == 0)
28+
{
29+
return BadRequest(new ProblemDetails
30+
{
31+
Title = "Invalid file",
32+
Detail = "No file provided or file is empty",
33+
Status = StatusCodes.Status400BadRequest
34+
});
35+
}
36+
37+
var fileInfo = new FileInfoResponse
38+
{
39+
FileName = file.FileName,
40+
Size = file.Length,
41+
ContentType = file.ContentType,
42+
UploadedAt = DateTime.UtcNow
43+
};
44+
45+
return Ok(fileInfo);
46+
}
47+
48+
/// <summary>
49+
/// Downloads a sample text file
50+
/// </summary>
51+
/// <param name="fileName">Optional custom filename for the downloaded file</param>
52+
/// <returns>A sample text file</returns>
53+
/// <response code="200">Returns the text file</response>
54+
[HttpGet("download")]
55+
[ProducesResponseType(StatusCodes.Status200OK)]
56+
[Produces("text/plain", "application/octet-stream")]
57+
public IActionResult DownloadFile([FromQuery] string? fileName = null)
58+
{
59+
// Create sample content in memory
60+
var content = $@"Sample Text File
61+
Generated on: {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC
62+
63+
This is a sample text file created in memory by the API.
64+
It contains some basic information and sample data.
65+
66+
Random GUID: {Guid.NewGuid()}
67+
Server Time: {DateTime.Now:F}
68+
69+
Thank you for using our file download API!";
70+
71+
var bytes = Encoding.UTF8.GetBytes(content);
72+
var defaultFileName = fileName ?? $"sample-file-{DateTime.UtcNow:yyyyMMdd-HHmmss}.txt";
73+
74+
return File(bytes, "text/plain", defaultFileName);
75+
}
76+
}
77+
78+
/// <summary>
79+
/// Response model for file upload information
80+
/// </summary>
81+
public class FileInfoResponse
82+
{
83+
/// <summary>
84+
/// Original filename of the uploaded file
85+
/// </summary>
86+
public string FileName { get; set; } = string.Empty;
87+
88+
/// <summary>
89+
/// Size of the file in bytes
90+
/// </summary>
91+
public long Size { get; set; }
92+
93+
/// <summary>
94+
/// Content type of the uploaded file
95+
/// </summary>
96+
public string? ContentType { get; set; }
97+
98+
/// <summary>
99+
/// Timestamp when the file was uploaded
100+
/// </summary>
101+
public DateTime UploadedAt { get; set; }
102+
}

src/c-sharp/JakubKozera.OpenApiUi.Sample/JakubKozera.OpenApiUi.Sample.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<GenerateDocumentationFile>true</GenerateDocumentationFile>
77
<NoWarn>$(NoWarn);1591</NoWarn>
88
</PropertyGroup> <ItemGroup>
9-
<PackageReference Include="JakubKozera.OpenApiUi" Version="1.0.12" />
9+
<PackageReference Include="JakubKozera.OpenApiUi" Version="1.0.14" />
1010
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.5" />
1111
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.4" />
1212
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.12.0" />

src/c-sharp/JakubKozera.OpenApiUi.Sample/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
{
8686
options.AddPolicy("GitHubPages", policy =>
8787
{
88-
policy.WithOrigins("https://jakubkozera.github.io")
88+
policy.WithOrigins("https://jakubkozera.github.io", "http://localhost:5501")
8989
.AllowAnyMethod()
9090
.AllowAnyHeader()
9191
.AllowCredentials();

src/c-sharp/JakubKozera.OpenApiUi.Sample/sample-requests.http

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,23 @@ Content-Type: application/json
114114
"tags": ["fail"],
115115
"isPublished": true
116116
}
117+
118+
### File Operations
119+
120+
### 17. Upload a file
121+
POST {{baseUrl}}/api/file/upload
122+
Content-Type: multipart/form-data; boundary=boundary
123+
124+
--boundary
125+
Content-Disposition: form-data; name="file"; filename="test.txt"
126+
Content-Type: text/plain
127+
128+
This is a test file content.
129+
You can replace this with any file content.
130+
--boundary--
131+
132+
### 18. Download a sample text file
133+
GET {{baseUrl}}/api/file/download
134+
135+
### 19. Download a sample text file with custom filename
136+
GET {{baseUrl}}/api/file/download?fileName=my-custom-file.txt

src/c-sharp/JakubKozera.OpenApiUi/JakubKozera.OpenApiUi.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<PropertyGroup>
33
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
44
<PackageId>JakubKozera.OpenApiUi</PackageId>
5-
<Version>1.0.12</Version>
5+
<Version>1.0.14</Version>
66
<Authors>Jakub Kozera</Authors>
77
<Description>A .NET library serving OpenAPI UI with HTML/CSS</Description>
88
<PackageTags>openapi;ui;html;css;dotnet</PackageTags>

src/c-sharp/JakubKozera.OpenApiUi/scripts/local-pack.ps1

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,35 @@ $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
55
$projectDir = Split-Path -Parent $scriptDir
66
$distDir = Join-Path (Split-Path -Parent (Split-Path -Parent $projectDir)) "core\dist"
77
$contentDir = Join-Path $projectDir "Content"
8+
$buildScriptPath = Join-Path (Split-Path -Parent (Split-Path -Parent $projectDir)) "core\build.js"
89

910
Write-Host "Project directory: $projectDir" -ForegroundColor Green
1011
Write-Host "Dist directory: $distDir" -ForegroundColor Green
1112
Write-Host "Content directory: $contentDir" -ForegroundColor Green
13+
Write-Host "Build script path: $buildScriptPath" -ForegroundColor Green
14+
15+
# First, run the build script to generate the dist files
16+
Write-Host "`nRunning build script..." -ForegroundColor Yellow
17+
if (-not (Test-Path $buildScriptPath)) {
18+
Write-Error "Build script not found: $buildScriptPath"
19+
exit 1
20+
}
21+
22+
try {
23+
Set-Location (Split-Path -Parent $buildScriptPath)
24+
node build.js
25+
26+
if ($LASTEXITCODE -ne 0) {
27+
throw "Build script failed"
28+
}
29+
30+
Write-Host "Build script completed successfully!" -ForegroundColor Green
31+
Set-Location $scriptDir
32+
}
33+
catch {
34+
Write-Error "Error running build script: $($_.Exception.Message)"
35+
exit 1
36+
}
1237

1338
# Check if dist directory exists
1439
if (-not (Test-Path $distDir)) {
@@ -93,7 +118,8 @@ try {
93118
}
94119
}
95120

96-
} catch {
121+
}
122+
catch {
97123
Write-Error "Error during build/pack process: $($_.Exception.Message)"
98124
exit 1
99125
}

src/core/demo-dist/bundle.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
html {
1111
scroll-behavior: smooth;
1212
}
13+
body {
14+
padding: 0 !important;
15+
}
16+
1317

1418
/* Make code samples scrollable horizontally */
1519
pre {

0 commit comments

Comments
 (0)