Hoi,
Ik zit met een design kwestie waar jullie wellicht bij zouden kunnen helpen. Ik heb al een tijdje een website draaien waar gebruikers een bepaald type bestand kunnen uploaden. Het gaat hier om 'setup' bestanden van race auto's voor een race spel (de afstelling van de auto dus). Bij het uploaden geven de gebruikers wat informatie over het bestand (zoals de auto en race track waarvoor het dient, de rondetijd die ermee gereden is, wie de afstelling gemaakt heeft, etc). Voor elk bestand wordt een unieke GUID gegenereerd bij het uploaden, en komt er een entry in mijn database met alle informatie (guid, auto, track, etc). Het bestand krijgt de GUID als naam en komt in een aparte map op de server te staan. De website toont dan een lijst met alle entries in de database, en wanneer een gebruiker een setup bestand wil downloaden kan de server simpelweg het bestand opzoeken via de GUID.
Naast deze website ben ik nu een Windows client aan het schrijven (WPF, C#), waarvan de bedoeling is dat hij periodiek alle nieuwe setup bestanden automatisch download. De gebruiker kan dan bijvoorbeeld een subscription nemen op een bepaalde auto, en periodiek worden dan alle setups van die auto opgehaald en gedownload. De communicatie tussen de client en de webserver verloopt simpelweg via een ASP.NET webservice.
De client gebruikt in eerste instantie enkel de entries uit de database, zodat de gebruiker het lijstje met setups en hun informatie te zien krijgt (maar nog niet meteen de bestanden zelf). Het downloaden verloopt dan via een aparte webmethod waar de GUID van een setup naartoe gestuurd wordt, waarna op de server het bestand ingelezen wordt en als bytes terug gestuurd wordt.
Een probleem is nu echter het automatisch downloaden van nieuwe setups. Op de een of andere manier moet ik bij zien te houden welke bestanden de gebruiker al (al dan niet automatisch) gedownload heeft, en welke bestanden nieuw zijn. Ik kan wel een aantal manieren bedenken maar alles heeft vrij grote nadelen.
1. De eerste optie was vrij simpel, namelijk op de client bijhouden wanneer de laatste 'synchronizatie' (automatische download) geweest is. Elke setup die daarna geupload wordt is nieuw en moet gedownload worden, en elke setup die voor die datum al bestond is oud en heeft de gebruiker al. Dit is vrij simpel te implementeren maar heeft duidelijk nadelen: de gebruiker kan de bestanden natuurlijk verwijderen (of stel hij gebruikt een nieuwe pc) waarna de client ze niet meer opnieuw zal downloaden.
2. Als tweede optie zou ik in de database (op de server) kunnen bijhouden welke gebruiker welke setup gedownload heeft. Dat doe ik momenteel al (met een extra boolean om aan te geven of de setup automatisch via de client gedownload is of gewoon handmatig via de website), maar ook hierbij geldt hetzelfde nadeel, ik kan niet controleren of het bestand nog steeds bestaat. Eigenlijk komt het erop neer dat ik alleen kan zien of een gebruiker een bestand download, maar ik kan daarna niet meer controleren wat hij er mee doet.
3. Als laatste optie had ik bedacht om een hash van de filecontents te maken. Elke keer als een nieuwe setup op de website geupload wordt hash ik de inhoudt (met MD5, dat is snel voor zover ik weet) en sla ik die ook op in de database. In die client kan ik nu van elk setup bestand ook een hash maken (de locatie van de bestanden is altijd een vaste plek), en zo weet ik precies welke setups er al op de pc van de gebruiker staan en welke nog niet. Zo zou ik alleen de setups kunnen laten tonen die de gebruiker nog niet heeft. Ik ga even voor het gemak er van uit dat de kans op conflicts verwaarloosbaar is en dat de bestanden echt hetzelfde zijn als de hash hetzelfde is.
Optie 3 vind ik zelf de mooiste maar heeft ook weer een groot nadeel: bij het opstarten van de client moet hij nu elke setup gaan inlezen en hashen, en ik had eigenlijk gehoopt dat dat iets sneller zou gaan maar het valt me behoorlijk tegen. Ik neem aan de MD5 hashen van deze bestanden (het gaat om < 5 kB per bestand) heel snel gaat, ik denk dat het inlezen van de bestanden de meeste tijd kost.
Ik gebruik de volgende method om alle .sto files in een bepaalde directory (en subdirectories) te hashen:
Het gaat in mijn geval om 1240 bestanden, wat volgens mij een relatief klein aantal bestanden is om te hashen, maar toch duurt het > 15 seconden, terwijl mijn harde schijf flink zit te ratelen.
Zijn er slimmere manieren om een dergelijk aantal bestanden te kunnen vergelijken met een bestand op de server, zonder meteen het hele bestand naar de client te downloaden?
Weten jullie misschien betere manieren waarop ik kan checken of een bestand (op de server) al bestaat op de client?
Bedankt!
Ik zit met een design kwestie waar jullie wellicht bij zouden kunnen helpen. Ik heb al een tijdje een website draaien waar gebruikers een bepaald type bestand kunnen uploaden. Het gaat hier om 'setup' bestanden van race auto's voor een race spel (de afstelling van de auto dus). Bij het uploaden geven de gebruikers wat informatie over het bestand (zoals de auto en race track waarvoor het dient, de rondetijd die ermee gereden is, wie de afstelling gemaakt heeft, etc). Voor elk bestand wordt een unieke GUID gegenereerd bij het uploaden, en komt er een entry in mijn database met alle informatie (guid, auto, track, etc). Het bestand krijgt de GUID als naam en komt in een aparte map op de server te staan. De website toont dan een lijst met alle entries in de database, en wanneer een gebruiker een setup bestand wil downloaden kan de server simpelweg het bestand opzoeken via de GUID.
Naast deze website ben ik nu een Windows client aan het schrijven (WPF, C#), waarvan de bedoeling is dat hij periodiek alle nieuwe setup bestanden automatisch download. De gebruiker kan dan bijvoorbeeld een subscription nemen op een bepaalde auto, en periodiek worden dan alle setups van die auto opgehaald en gedownload. De communicatie tussen de client en de webserver verloopt simpelweg via een ASP.NET webservice.
De client gebruikt in eerste instantie enkel de entries uit de database, zodat de gebruiker het lijstje met setups en hun informatie te zien krijgt (maar nog niet meteen de bestanden zelf). Het downloaden verloopt dan via een aparte webmethod waar de GUID van een setup naartoe gestuurd wordt, waarna op de server het bestand ingelezen wordt en als bytes terug gestuurd wordt.
Een probleem is nu echter het automatisch downloaden van nieuwe setups. Op de een of andere manier moet ik bij zien te houden welke bestanden de gebruiker al (al dan niet automatisch) gedownload heeft, en welke bestanden nieuw zijn. Ik kan wel een aantal manieren bedenken maar alles heeft vrij grote nadelen.
1. De eerste optie was vrij simpel, namelijk op de client bijhouden wanneer de laatste 'synchronizatie' (automatische download) geweest is. Elke setup die daarna geupload wordt is nieuw en moet gedownload worden, en elke setup die voor die datum al bestond is oud en heeft de gebruiker al. Dit is vrij simpel te implementeren maar heeft duidelijk nadelen: de gebruiker kan de bestanden natuurlijk verwijderen (of stel hij gebruikt een nieuwe pc) waarna de client ze niet meer opnieuw zal downloaden.
2. Als tweede optie zou ik in de database (op de server) kunnen bijhouden welke gebruiker welke setup gedownload heeft. Dat doe ik momenteel al (met een extra boolean om aan te geven of de setup automatisch via de client gedownload is of gewoon handmatig via de website), maar ook hierbij geldt hetzelfde nadeel, ik kan niet controleren of het bestand nog steeds bestaat. Eigenlijk komt het erop neer dat ik alleen kan zien of een gebruiker een bestand download, maar ik kan daarna niet meer controleren wat hij er mee doet.
3. Als laatste optie had ik bedacht om een hash van de filecontents te maken. Elke keer als een nieuwe setup op de website geupload wordt hash ik de inhoudt (met MD5, dat is snel voor zover ik weet) en sla ik die ook op in de database. In die client kan ik nu van elk setup bestand ook een hash maken (de locatie van de bestanden is altijd een vaste plek), en zo weet ik precies welke setups er al op de pc van de gebruiker staan en welke nog niet. Zo zou ik alleen de setups kunnen laten tonen die de gebruiker nog niet heeft. Ik ga even voor het gemak er van uit dat de kans op conflicts verwaarloosbaar is en dat de bestanden echt hetzelfde zijn als de hash hetzelfde is.
Optie 3 vind ik zelf de mooiste maar heeft ook weer een groot nadeel: bij het opstarten van de client moet hij nu elke setup gaan inlezen en hashen, en ik had eigenlijk gehoopt dat dat iets sneller zou gaan maar het valt me behoorlijk tegen. Ik neem aan de MD5 hashen van deze bestanden (het gaat om < 5 kB per bestand) heel snel gaat, ik denk dat het inlezen van de bestanden de meeste tijd kost.
Ik gebruik de volgende method om alle .sto files in een bepaalde directory (en subdirectories) te hashen:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
| public static void ComputeHashes() { _fileHashes = new Dictionary<byte[], string>(); using (var md5 = MD5.Create()) foreach (var file in Directory.GetFiles(_setupsPath, "*.sto", SearchOption.AllDirectories)) { var contents = File.ReadAllBytes(file); var hash = md5.ComputeHash(contents); _fileHashes.Add(hash, file); } } |
Het gaat in mijn geval om 1240 bestanden, wat volgens mij een relatief klein aantal bestanden is om te hashen, maar toch duurt het > 15 seconden, terwijl mijn harde schijf flink zit te ratelen.
Zijn er slimmere manieren om een dergelijk aantal bestanden te kunnen vergelijken met een bestand op de server, zonder meteen het hele bestand naar de client te downloaden?
Weten jullie misschien betere manieren waarop ik kan checken of een bestand (op de server) al bestaat op de client?
Bedankt!