上传源代码版本
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
195
test/Base64PdfValidator/Base64PdfValidator/Program.cs
Normal file
195
test/Base64PdfValidator/Base64PdfValidator/Program.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Base64PdfValidator
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("=== Base64 PDF Validator and Converter ===");
|
||||
Console.WriteLine("This program validates if a base64 string represents a valid PDF file and converts it to PDF.");
|
||||
Console.WriteLine();
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.Write("Enter base64 encoded PDF string (or 'exit' to quit): ");
|
||||
string input = Console.ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input) || input.Equals("exit", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Trim any whitespace or potential data URL prefix
|
||||
string base64Data = input.Trim();
|
||||
if (base64Data.StartsWith("data:"))
|
||||
{
|
||||
// Extract base64 data from data URL
|
||||
int base64Index = base64Data.IndexOf(",");
|
||||
if (base64Index > 0)
|
||||
{
|
||||
base64Data = base64Data.Substring(base64Index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate base64 format
|
||||
if (!IsValidBase64(base64Data))
|
||||
{
|
||||
Console.WriteLine("❌ Invalid base64 format.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Decode base64 to bytes
|
||||
byte[] pdfBytes = Convert.FromBase64String(base64Data);
|
||||
Console.WriteLine($"✅ Successfully decoded base64 to {pdfBytes.Length} bytes.");
|
||||
|
||||
// Validate if it's a PDF
|
||||
if (IsValidPdf(pdfBytes))
|
||||
{
|
||||
Console.WriteLine("✅ Valid PDF file format detected.");
|
||||
|
||||
// Save as PDF
|
||||
string fileName = $"output_{DateTime.Now:yyyyMMdd_HHmmss}.pdf";
|
||||
File.WriteAllBytes(fileName, pdfBytes);
|
||||
Console.WriteLine($"✅ PDF file saved as: {fileName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("❌ Not a valid PDF file.");
|
||||
|
||||
// Try to detect file type from header
|
||||
string detectedType = DetectFileType(pdfBytes);
|
||||
if (!string.IsNullOrEmpty(detectedType))
|
||||
{
|
||||
Console.WriteLine($"📄 Detected file type: {detectedType}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"❌ Error: {ex.Message}");
|
||||
Console.WriteLine($"📋 Stack trace: {ex.StackTrace}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Program exited.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates if a string is valid base64
|
||||
/// </summary>
|
||||
private static bool IsValidBase64(string base64)
|
||||
{
|
||||
try
|
||||
{
|
||||
Convert.FromBase64String(base64);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates if bytes represent a valid PDF file
|
||||
/// </summary>
|
||||
private static bool IsValidPdf(byte[] bytes)
|
||||
{
|
||||
if (bytes == null || bytes.Length < 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// PDF files start with "%PDF-"
|
||||
byte[] pdfHeader = Encoding.ASCII.GetBytes("%PDF-");
|
||||
for (int i = 0; i < pdfHeader.Length; i++)
|
||||
{
|
||||
if (bytes[i] != pdfHeader[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Check for "%%EOF" at the end (more reliable)
|
||||
if (bytes.Length > 5)
|
||||
{
|
||||
byte[] pdfFooter = Encoding.ASCII.GetBytes("%%EOF");
|
||||
int footerIndex = bytes.Length - pdfFooter.Length;
|
||||
|
||||
// Check if footer exists at the end
|
||||
bool hasFooter = true;
|
||||
for (int i = 0; i < pdfFooter.Length; i++)
|
||||
{
|
||||
if (bytes[footerIndex + i] != pdfFooter[i])
|
||||
{
|
||||
hasFooter = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For more robust validation, we could check for "%%EOF" anywhere in the last 100 bytes
|
||||
if (!hasFooter)
|
||||
{
|
||||
// Search for "%%EOF" in the last 100 bytes
|
||||
int searchStart = Math.Max(0, bytes.Length - 100);
|
||||
string lastPart = Encoding.ASCII.GetString(bytes, searchStart, bytes.Length - searchStart);
|
||||
return lastPart.Contains("%%EOF");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to detect the file type from its header bytes
|
||||
/// </summary>
|
||||
private static string DetectFileType(byte[] bytes)
|
||||
{
|
||||
if (bytes == null || bytes.Length < 4)
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
// Check common file signatures (magic numbers)
|
||||
if (bytes[0] == 0x25 && bytes[1] == 0x50 && bytes[2] == 0x44 && bytes[3] == 0x46) // %PDF
|
||||
{
|
||||
return "PDF";
|
||||
}
|
||||
else if (bytes[0] == 0xFF && bytes[1] == 0xD8) // JPEG
|
||||
{
|
||||
return "JPEG/JPG";
|
||||
}
|
||||
else if (bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4E && bytes[3] == 0x47) // PNG
|
||||
{
|
||||
return "PNG";
|
||||
}
|
||||
else if (bytes[0] == 0x47 && bytes[1] == 0x49 && bytes[2] == 0x46) // GIF
|
||||
{
|
||||
return "GIF";
|
||||
}
|
||||
else if (bytes[0] == 0x50 && bytes[1] == 0x4B && bytes[2] == 0x03 && bytes[3] == 0x04) // ZIP
|
||||
{
|
||||
return "ZIP/Office Document";
|
||||
}
|
||||
else if (bytes[0] == 0x00 && bytes[1] == 0x00 && bytes[2] == 0x01 && bytes[3] == 0xBA) // MP4
|
||||
{
|
||||
return "MP4";
|
||||
}
|
||||
else if (bytes[0] == 0x42 && bytes[1] == 0x4D) // BMP
|
||||
{
|
||||
return "BMP";
|
||||
}
|
||||
|
||||
return "Unknown file type";
|
||||
}
|
||||
}
|
||||
}
|
||||
18
test/LogConfigTest/LogConfigTest.csproj
Normal file
18
test/LogConfigTest/LogConfigTest.csproj
Normal file
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
64
test/LogConfigTest/Program.cs
Normal file
64
test/LogConfigTest/Program.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace LogConfigTest
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 加载配置文件
|
||||
var config = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.Build();
|
||||
|
||||
// 配置Serilog
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.ReadFrom.Configuration(config)
|
||||
.CreateLogger();
|
||||
|
||||
Console.WriteLine("日志配置成功!");
|
||||
Console.WriteLine("正在测试日志写入...");
|
||||
|
||||
// 写入测试日志
|
||||
Log.Information("这是一条信息日志");
|
||||
Log.Warning("这是一条警告日志");
|
||||
Log.Error("这是一条错误日志");
|
||||
|
||||
Console.WriteLine("日志写入完成,请检查logs目录下的日志文件。");
|
||||
|
||||
// 检查日志目录
|
||||
if (Directory.Exists("logs"))
|
||||
{
|
||||
Console.WriteLine("\n日志目录已创建,包含以下文件:");
|
||||
var logFiles = Directory.GetFiles("logs");
|
||||
foreach (var file in logFiles)
|
||||
{
|
||||
Console.WriteLine($"- {Path.GetFileName(file)}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("\n日志目录尚未创建,请稍候再试。");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"配置错误: {ex.Message}");
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
|
||||
Console.WriteLine("\n按任意键退出...");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
25
test/LogConfigTest/appsettings.json
Normal file
25
test/LogConfigTest/appsettings.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning",
|
||||
"System": "Warning"
|
||||
}
|
||||
},
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "logs/api_log-.txt",
|
||||
"rollingInterval": "Day",
|
||||
"fileSizeLimitBytes": 10485760,
|
||||
"rollOnFileSizeLimit": true,
|
||||
"retainedFileCountLimit": 30,
|
||||
"shared": true,
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext}: {Message}{NewLine}{Exception}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user