Skip to content

Commit 4ef22ef

Browse files
committed
add excel upload handler
1 parent ecd21e8 commit 4ef22ef

14 files changed

Lines changed: 618 additions & 33 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,3 +406,4 @@ appsettings.Development.json
406406
*/k6/*.csv
407407
*/k6/*.text
408408
/*.DotSettings
409+
dist/

NpgsqlRest/NpgsqlRestMiddleware.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,9 +1648,11 @@ uploadHandler is not null &&
16481648
} // end if (routine.ReturnsRecord == true)
16491649
} // end if (routine.IsVoid is false)
16501650
}
1651-
catch (NpgsqlException exception)
1651+
catch (Exception exception)
16521652
{
1653-
if (options.PostgreSqlErrorCodeToHttpStatusCodeMapping.TryGetValue(exception.SqlState ?? "", out var code))
1653+
string? sqlState = exception is NpgsqlException npgsqlEx ? npgsqlEx.SqlState : null;
1654+
1655+
if (options.PostgreSqlErrorCodeToHttpStatusCodeMapping.TryGetValue(sqlState ?? "", out var code))
16541656
{
16551657
context.Response.StatusCode = code;
16561658
}
@@ -1665,7 +1667,7 @@ uploadHandler is not null &&
16651667
ReadOnlySpan<char> msg;
16661668
if (context.Response.StatusCode == 400)
16671669
{
1668-
msg = exception.Message.Replace(string.Concat(exception.SqlState, ": "), "").AsSpan();
1670+
msg = exception.Message.Replace(string.Concat(sqlState, ": "), "").AsSpan();
16691671
}
16701672
else
16711673
{

NpgsqlRest/PgConverters.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@ public static class PgConverters
2727
Justification = "Serializes only string type that have AOT friendly TypeInfoResolver")]
2828
[UnconditionalSuppressMessage("Aot", "IL3050:RequiresDynamic",
2929
Justification = "Serializes only string type that have AOT friendly TypeInfoResolver")]
30-
internal static string SerializeString(string value) => JsonSerializer.Serialize(value, PlainTextSerializerOptions);
30+
public static string SerializeString(string value) => JsonSerializer.Serialize(value, PlainTextSerializerOptions);
3131

3232
[UnconditionalSuppressMessage("Aot", "IL2026:RequiresUnreferencedCode",
3333
Justification = "Serializes only string type that have AOT friendly TypeInfoResolver")]
3434
[UnconditionalSuppressMessage("Aot", "IL3050:RequiresDynamic",
3535
Justification = "Serializes only string type that have AOT friendly TypeInfoResolver")]
36-
internal static string SerializeObject(object? value) => JsonSerializer.Serialize(value, PlainTextSerializerOptions);
36+
public static string SerializeObject(object? value) => JsonSerializer.Serialize(value, PlainTextSerializerOptions);
3737

3838
[UnconditionalSuppressMessage("Aot", "IL2026:RequiresUnreferencedCode",
3939
Justification = "Serializes only string type that have AOT friendly TypeInfoResolver")]
4040
[UnconditionalSuppressMessage("Aot", "IL3050:RequiresDynamic",
4141
Justification = "Serializes only string type that have AOT friendly TypeInfoResolver")]
42-
internal static string SerializeString(ref ReadOnlySpan<char> value) => JsonSerializer.Serialize(value.ToString(), PlainTextSerializerOptions);
42+
public static string SerializeString(ref ReadOnlySpan<char> value) => JsonSerializer.Serialize(value.ToString(), PlainTextSerializerOptions);
4343

4444
internal static ReadOnlySpan<char> PgUnknownToJsonArray(ref ReadOnlySpan<char> value)
4545
{

NpgsqlRest/UploadHandlers/FileCheckExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static bool CheckMimeTypes(this string contentType, string[]? includedMim
4747
return true;
4848
}
4949

50-
public static async Task<UploadFileStatus> CheckFileStatus(
50+
public static async Task<UploadFileStatus> CheckTextContentStatus(
5151
this IFormFile formFile,
5252
int testBufferSize = 4096,
5353
int nonPrintableThreshold = 5,

NpgsqlRest/UploadHandlers/Handlers/CsvUploadHandler.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@ public async Task<string> UploadAsync(NpgsqlConnection connection, HttpContext c
7575

7676
if (options.LogUploadParameters is true)
7777
{
78-
logger?.LogInformation("Upload for {_type}: includedMimeTypePatterns={includedMimeTypePatterns}, excludedMimeTypePatterns={excludedMimeTypePatterns}, checkFileStatus={checkFileStatus}, testBufferSize={testBufferSize}, nonPrintableThreshold={nonPrintableThreshold}, delimiters={delimiters}, hasFieldsEnclosedInQuotes={hasFieldsEnclosedInQuotes}, setWhiteSpaceToNull={setWhiteSpaceToNull}, rowCommand={rowCommand}",
78+
#pragma warning disable CA2253 // Named placeholders should not be numeric values
79+
logger?.LogInformation("Upload for {0}: includedMimeTypePatterns={1}, excludedMimeTypePatterns={2}, checkFileStatus={3}, testBufferSize={4}, nonPrintableThreshold={5}, delimiters={6}, hasFieldsEnclosedInQuotes={7}, setWhiteSpaceToNull={8}, rowCommand={9}",
7980
_type, includedMimeTypePatterns, excludedMimeTypePatterns, checkFileStatus, testBufferSize, nonPrintableThreshold, delimiters, hasFieldsEnclosedInQuotes, setWhiteSpaceToNull, rowCommand);
81+
#pragma warning disable CA2253 // Named placeholders should not be numeric values
8082
}
8183

8284
string[] delimitersArr = [.. delimiters.Select(c => c.ToString())];
@@ -122,7 +124,7 @@ public async Task<string> UploadAsync(NpgsqlConnection connection, HttpContext c
122124
}
123125
if (status == UploadFileStatus.Ok && checkFileStatus is true)
124126
{
125-
status = await formFile.CheckFileStatus(testBufferSize, nonPrintableThreshold, checkNewLines: true);
127+
status = await formFile.CheckTextContentStatus(testBufferSize, nonPrintableThreshold, checkNewLines: true);
126128
}
127129
fileJson.Append(",\"success\":");
128130
fileJson.Append(status == UploadFileStatus.Ok ? "true" : "false");
@@ -132,6 +134,7 @@ public async Task<string> UploadAsync(NpgsqlConnection connection, HttpContext c
132134
if (status != UploadFileStatus.Ok)
133135
{
134136
logger?.FileUploadFailed(_type, formFile.FileName, formFile.ContentType, formFile.Length, status);
137+
result.Append(fileJson);
135138
fileId++;
136139
continue;
137140
}

NpgsqlRest/UploadHandlers/Handlers/FileSystemUploadHandler.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@ public async Task<string> UploadAsync(NpgsqlConnection connection, HttpContext c
9393

9494
if (options.LogUploadParameters is true)
9595
{
96-
logger?.LogInformation("Upload for {_type}: includedMimeTypePatterns={includedMimeTypePatterns}, excludedMimeTypePatterns={excludedMimeTypePatterns}, bufferSize={bufferSize}, basePath={basePath}, useUniqueFileName={useUniqueFileName}, newFileName={newFileName}, createPathIfNotExists={createPathIfNotExists}, checkText={checkText}, checkImage={checkImage}, allowedImage={allowedImage}, testBufferSize={testBufferSize}, nonPrintableThreshold={nonPrintableThreshold}",
96+
#pragma warning disable CA2253 // Named placeholders should not be numeric values
97+
logger?.LogInformation("Upload for {0}: includedMimeTypePatterns={1}, excludedMimeTypePatterns={2}, bufferSize={3}, basePath={4}, useUniqueFileName={5}, newFileName={6}, createPathIfNotExists={7}, checkText={8}, checkImage={9}, allowedImage={10}, testBufferSize={11}, nonPrintableThreshold={12}",
9798
_type, includedMimeTypePatterns, excludedMimeTypePatterns, bufferSize, basePath, useUniqueFileName, newFileName, createPathIfNotExists, checkText, checkImage, allowedImage, testBufferSize, nonPrintableThreshold);
99+
#pragma warning disable CA2253 // Named placeholders should not be numeric values
98100
}
99101

100102
if (createPathIfNotExists is true && Directory.Exists(basePath) is false)
@@ -153,7 +155,7 @@ public async Task<string> UploadAsync(NpgsqlConnection connection, HttpContext c
153155
{
154156
if (checkText is true)
155157
{
156-
status = await formFile.CheckFileStatus(testBufferSize, nonPrintableThreshold, checkNewLines: false);
158+
status = await formFile.CheckTextContentStatus(testBufferSize, nonPrintableThreshold, checkNewLines: false);
157159
}
158160
if (status == UploadFileStatus.Ok && checkImage is true)
159161
{

NpgsqlRest/UploadHandlers/Handlers/LargeObjectUploadHandler.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ public async Task<string> UploadAsync(NpgsqlConnection connection, HttpContext c
6767

6868
if (options.LogUploadParameters is true)
6969
{
70-
logger?.LogInformation("Upload for {_type}: includedMimeTypePatterns={includedMimeTypePatterns}, excludedMimeTypePatterns={excludedMimeTypePatterns}, bufferSize={bufferSize}, oid={oid}, checkText={checkText}, checkImage={checkImage}, allowedImage={allowedImage}, testBufferSize={testBufferSize}, nonPrintableThreshold={nonPrintableThreshold}",
70+
#pragma warning disable CA2253 // Named placeholders should not be numeric values
71+
logger?.LogInformation("Upload for {0}: includedMimeTypePatterns={1}, excludedMimeTypePatterns={2}, bufferSize={3}, oid={4}, checkText={5}, checkImage={6}, allowedImage={7}, testBufferSize={8}, nonPrintableThreshold={9}",
7172
_type, includedMimeTypePatterns, excludedMimeTypePatterns, bufferSize, oid, checkText, checkImage, allowedImage, testBufferSize, nonPrintableThreshold);
73+
#pragma warning disable CA2253 // Named placeholders should not be numeric values
7274
}
7375

7476
StringBuilder result = new(context.Request.Form.Files.Count*100);
@@ -107,7 +109,7 @@ public async Task<string> UploadAsync(NpgsqlConnection connection, HttpContext c
107109
{
108110
if (checkText is true)
109111
{
110-
status = await formFile.CheckFileStatus(testBufferSize, nonPrintableThreshold, checkNewLines: false);
112+
status = await formFile.CheckTextContentStatus(testBufferSize, nonPrintableThreshold, checkNewLines: false);
111113
}
112114
if (status == UploadFileStatus.Ok && checkImage is true)
113115
{
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
namespace NpgsqlRest.UploadHandlers;
22

3-
public enum UploadFileStatus { Empty, ProbablyBinary, InvalidImage, NoNewLines, InvalidMimeType, Ok }
3+
public enum UploadFileStatus
4+
{
5+
Empty,
6+
ProbablyBinary,
7+
InvalidImage,
8+
InvalidFileFormat,
9+
NoNewLines,
10+
InvalidMimeType,
11+
Ok
12+
}

NpgsqlRestClient/App.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,14 +479,30 @@ public static NpgsqlRestUploadOptions CreateUploadOptions()
479479
result.DefaultUploadHandlerOptions = uploadHandlerOptions;
480480

481481
result.UploadHandlers = result.CreateUploadHandlers();
482-
if (result.UploadHandlers is not null && result.UploadHandlers.Count > 1)
482+
483+
if (GetConfigBool("ExcelUploadEnabled", uploadHandlersCfg, true))
484+
{
485+
ExcelUploadOptions.Instance.ExcelUploadCheckFileStatus = GetConfigBool("ExcelUploadCheckFileStatus", uploadHandlersCfg, true);
486+
487+
ExcelUploadOptions.Instance.ExcelSheetName = GetConfigStr("ExcelSheetName", uploadHandlersCfg) ?? null;
488+
ExcelUploadOptions.Instance.ExcelAllSheets = GetConfigBool("ExcelAllSheets", uploadHandlersCfg, false);
489+
ExcelUploadOptions.Instance.ExcelTimeFormat = GetConfigStr("ExcelTimeFormat", uploadHandlersCfg) ?? "HH:mm:ss";
490+
ExcelUploadOptions.Instance.ExcelDateFormat = GetConfigStr("ExcelDateFormat", uploadHandlersCfg) ?? "yyyy-MM-dd";
491+
ExcelUploadOptions.Instance.ExcelDateTimeFormat = GetConfigStr("ExcelDateTimeFormat", uploadHandlersCfg) ?? "yyyy-MM-dd HH:mm:ss";
492+
ExcelUploadOptions.Instance.ExcelRowDataAsJson = GetConfigBool("ExcelRowDataAsJson", uploadHandlersCfg, false);
493+
ExcelUploadOptions.Instance.ExcelUploadRowCommand = GetConfigStr("ExcelUploadRowCommand", uploadHandlersCfg) ?? "call process_excel_row($1,$2,$3,$4)";
494+
495+
result?.UploadHandlers?.Add(GetConfigStr("ExcelKey", uploadHandlersCfg) ?? "excel", logger => new ExcelUploadHandler(result, logger));
496+
}
497+
498+
if (result?.UploadHandlers is not null && result.UploadHandlers.Count > 1)
483499
{
484500
Logger?.Information("Using {0} upload handlers where {1} is default.", result.UploadHandlers.Keys, result.DefaultUploadHandler);
485501
foreach (var uploadHandler in result.UploadHandlers)
486502
{
487503
Logger?.Information("Upload handler {0} has following parameters: {1}", uploadHandler.Key, uploadHandler.Value(null!).SetType(uploadHandler.Key).Parameters);
488504
}
489505
}
490-
return result;
506+
return result!;
491507
}
492508
}

NpgsqlRestClient/Arguments.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public static (List<(string fileName, bool optional)> configFiles, string[] comm
8181
{
8282
nextIsOptional = true;
8383
}
84-
else if (arg.StartsWith("--") && arg.Contains("="))
84+
else if (arg.StartsWith("--") && arg.Contains('='))
8585
{
8686
commandLineArgs.Add(arg);
8787
}

0 commit comments

Comments
 (0)