Repository navigation
Expand file tree
/
Copy pathProgram.cs
More file actions
159 lines (121 loc) · 4.61 KB
/
Copy pathProgram.cs
File metadata and controls
159 lines (121 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text.RegularExpressions;
using QRCoder;
const int Port = 8080;
const long MaxUploadBytes = 100L * 1024 * 1024;
const string AppFolderName = "PhotoDrop";
var outputDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
AppFolderName);
Directory.CreateDirectory(outputDirectory);
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls($"http://0.0.0.0:{Port}");
builder.WebHost.ConfigureKestrel(options =>
options.Limits.MaxRequestBodySize = MaxUploadBytes);
var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapGet("/api/status", () =>
{
var primaryAddress = GetPrimaryAddress();
return Results.Ok(new
{
primaryAddress,
addresses = GetLocalAddresses().Select(ip => $"http://{ip}:{Port}"),
outputDirectory,
maxUploadMb = MaxUploadBytes / 1024 / 1024
});
});
app.MapGet("/api/qr", () =>
{
var primaryAddress = GetPrimaryAddress();
if (primaryAddress is null)
return Results.NotFound();
using var generator = new QRCodeGenerator();
using var data = generator.CreateQrCode(primaryAddress, QRCodeGenerator.ECCLevel.Q);
var png = new PngByteQRCode(data).GetGraphic(20);
return Results.File(png, "image/png");
});
app.MapPost("/api/upload", async (HttpRequest request) =>
{
if (!request.HasFormContentType)
return Results.BadRequest(new { error = "Expected a file upload." });
var form = await request.ReadFormAsync();
var file = form.Files.GetFile("photo");
if (file is null || file.Length == 0)
return Results.BadRequest(new { error = "No file selected." });
if (file.Length > MaxUploadBytes)
return Results.BadRequest(new { error = "File is too large." });
if (!file.ContentType.Equals("image/jpeg", StringComparison.OrdinalIgnoreCase))
return Results.BadRequest(new { error = "Only JPEG images are accepted." });
var baseName = Regex.Replace(
Path.GetFileNameWithoutExtension(file.FileName),
"[^a-zA-Z0-9а-яА-ЯёЁ _-]",
"_");
if (string.IsNullOrWhiteSpace(baseName))
baseName = "photo";
var path = CreateUniquePath(outputDirectory, baseName, ".jpg");
await using var destination = File.Create(path);
await file.CopyToAsync(destination);
Console.WriteLine($"Received: {Path.GetFileName(path)} ({file.Length / 1024:N0} KB)");
return Results.Ok(new
{
savedAs = Path.GetFileName(path)
});
});
Console.WriteLine("PhotoDrop is running.");
Console.WriteLine($"Photos will be saved to: {outputDirectory}");
foreach (var address in GetLocalAddresses())
{
Console.WriteLine($"Open this address on your iPhone: http://{address}:{Port}");
}
Console.WriteLine("Press Ctrl+C to stop the server.");
app.Run();
static IEnumerable<IPAddress> GetLocalAddresses() =>
NetworkInterface.GetAllNetworkInterfaces()
.Where(network =>
network.OperationalStatus == OperationalStatus.Up &&
network.NetworkInterfaceType != NetworkInterfaceType.Loopback &&
network.GetIPProperties().GatewayAddresses.Any(gateway =>
gateway.Address.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.Any.Equals(gateway.Address)))
.SelectMany(network => network.GetIPProperties().UnicastAddresses)
.Select(unicast => unicast.Address)
.Where(address =>
address.AddressFamily == AddressFamily.InterNetwork &&
!IPAddress.IsLoopback(address) &&
IsPrivateLanAddress(address))
.Distinct()
.OrderBy(GetLanPriority);
static string? GetPrimaryAddress()
{
foreach (var address in GetLocalAddresses())
return $"http://{address}:{Port}";
return null;
}
static bool IsPrivateLanAddress(IPAddress address)
{
var bytes = address.GetAddressBytes();
return bytes[0] == 192 && bytes[1] == 168 ||
bytes[0] == 10 ||
bytes[0] == 172 && bytes[1] is >= 16 and <= 31;
}
static int GetLanPriority(IPAddress address)
{
var bytes = address.GetAddressBytes();
return bytes[0] == 192 && bytes[1] == 168 ? 0 :
bytes[0] == 10 ? 1 : 2;
}
static string CreateUniquePath(string directory, string baseName, string extension)
{
var stamp = DateTime.Now.ToString("yyyyMMdd-HHmmss");
for (var index = 0;; index++)
{
var suffix = index == 0 ? string.Empty : $"-{index}";
var path = Path.Combine(directory, $"{baseName}-{stamp}{suffix}{extension}");
if (!File.Exists(path))
return path;
}
}