Jakie jest najlepsze miejsce do przechowywania przesłanych obrazów, bazy danych SQL lub systemu plików na dysku?

146

Piszę aplikację, która pozwala użytkownikom przesyłać obrazy na serwer. Spodziewam się około 20 obrazów dziennie w całości w formacie jpeg i prawdopodobnie nie będzie edytowanych / zmienianych rozmiarów. (To jest kolejne pytanie, jak zmienić rozmiar obrazów po stronie serwera przed przechowywaniem. Może ktoś może zostawić w komentarzu zasób .NET). Zastanawiam się teraz, jakie jest najlepsze miejsce do przechowywania przesłanych zdjęć.

  • Zapisz obrazy jako plik w systemie plików i utwórz rekord w tabeli z dokładną ścieżką do tego obrazu.

  • Lub przechowuj sam obraz w tabeli przy użyciu typu danych „obraz” lub „dane binarne” serwera bazy danych.

W obu dostrzegam zalety i wady. Podoba mi się a), ponieważ mogę łatwo przenieść pliki i po prostu zmienić wpis w tabeli. Z drugiej strony nie lubię przechowywać danych biznesowych na serwerze WWW i nie chcę łączyć serwera WWW z żadnym innym źródłem danych, które przechowuje dane biznesowe (ze względów bezpieczeństwa), które lubię b) ponieważ wszystkie informacje są w jednym miejscu i łatwo dostępne za pomocą zapytania. Z drugiej strony baza danych wkrótce stanie się bardzo duża. Outsourcing tych danych może być trudniejszy.

Tobias
źródło
2
Nie znalazłem tego, gdzie?
Tobias,

Odpowiedzi:

95

Generalnie przechowuję pliki w systemie plików, ponieważ po to tam jest, chociaż są wyjątki. W przypadku plików system plików jest najbardziej elastycznym i wydajnym rozwiązaniem (zwykle).

Istnieje kilka problemów z przechowywaniem plików w bazie danych - pliki są na ogół znacznie większe niż przeciętny wiersz - zestawy wyników zawierające wiele dużych plików zajmują dużo pamięci. Ponadto, jeśli używasz silnika pamięci masowej, który używa blokad tabeli do zapisu (na przykład ISAM), twoja tabela plików może być często blokowana w zależności od rozmiaru / szybkości plików, które tam przechowujesz.

Jeśli chodzi o bezpieczeństwo - zwykle przechowuję pliki w katalogu, który znajduje się poza katalogiem głównym (niedostępnym przez żądanie http) i udostępniam je za pośrednictwem skryptu, który najpierw sprawdza prawidłową autoryzację.

Eran Galperin
źródło
7
Czy mógłbyś wyjaśnić mi ostatni akapit (dotyczący bezpieczeństwa) pod względem szczegółów technicznych lub wszelkich wskazówek, które byłyby bardzo pomocne. Dziękuję Ci.
VishwaKumar
39
(Dla wszystkich pracowników Google) Jeśli masz katalog główny swojej witryny skonfigurowany w folderze „publicznym” (np. Moja_witryna / public / zamiast tylko moja_witryna /), możesz przechowywać obrazy w folderze moja_witryna / moje_obrazki razem z resztą Twoja aplikacja. Wtedy tagi img odwoływałyby się do „my_website / image.php? Img_id = 55” zamiast do „my_website / avatar.png”, a skrypt image.php po sprawdzeniu poświadczeń i przeanalizowaniu podanego identyfikatora zwróciłby rzeczywisty wizerunek. W ten sposób obraz będzie widoczny tylko dla odpowiednio zalogowanego użytkownika.
Captain Hypertext
8
hej kapitanie, powinieneś zamienić to w prawdziwą odpowiedź, abyś mógł zdobyć punkty $$$
Andrew
4
dodaj jeszcze kilka uwag na temat bezpieczeństwa / zapobiegania niszczeniu plików przez Twoją witrynę internetową
Andrew
1
To nie byłoby skalowalne, istnieje ograniczenie liczby plików w folderze, a jeśli planujesz podzielić pliki na wiele folderów, zwiększyłoby to złożoność indeksowania plików (aby zidentyfikować, gdzie plik jest faktycznie przechowywany). Ponadto wyszukiwanie będzie bardzo powolne.
Hardik
43

Jedyną korzyścią dla opcji B jest posiadanie wszystkich danych w jednym systemie, ale jest to fałszywa korzyść! Możesz argumentować, że Twój kod jest również formą danych, a zatem może być również przechowywany w bazie danych - jak byś chciał?

Chyba że masz jakiś wyjątkowy przypadek:

  • Logika biznesowa należy do kodu.
  • Dane strukturalne należą do bazy danych (relacyjne lub nierelacyjne).
  • Dane masowe należą do pamięci masowej (system plików lub inny).

Pliki, kod, dane

Nie jest konieczne używanie systemu plików do przechowywania plików. Zamiast tego możesz korzystać z pamięci masowej w chmurze (takiej jak Amazon S3 ) lub infrastruktury jako usługi (takiej jak Uploadcare ):

https://uploadcare.com/upload-api-cloud-storage-and-cdn/

Ale przechowywanie plików w bazie danych to zły pomysł.

David Avsajanishvili
źródło
23

Flickr używa systemu plików - tutaj omawiają przyczyny

Martin Beckett
źródło
14

Wiem, że to stary post. Ale wielu odwiedzających tę stronę nie otrzymuje nic związanego z tym pytaniem. Szczególnie dla początkujących.

Jak przesłać i przechowywać obrazy lub plik na naszej stronie internetowej:

W przypadku statycznej witryny internetowej może nie być problemu, ponieważ przechowywanie plików dla niektórych hostów współdzielonych jest nadal wystarczające. Problem pojawia się w przypadku dynamicznej witryny internetowej, gdy staje się ona większa. Większe w bazie danych można obsłużyć, ale większe pliki, takie jak obrazy, stają się problemem. W witrynie istnieją dwa rodzaje obrazów:

  1. Obrazy pochodzą od administratora dynamicznego bloga. Zazwyczaj te obrazy zostały zoptymalizowane przed przesłaniem.

  2. Obrazy od użytkowników w przypadku użytkowników mogą przesyłać obrazy, takie jak awatar. Lub użytkownicy mogą tworzyć zawartość bloga i umieszczać obrazy z edytora tekstu. Tego rodzaju obrazy są trudne do przewidzenia. Użytkownicy mogą przesyłać duże obrazy tylko dla małych treści, zmieniając rozmiar widoku, ale nie zmieniając rozmiaru obrazu.

Ignorując nr pozycji. 1 powyżej, szybkie rozwiązanie dla pozycji nr. 2 można tymczasowo rozwiązać za pomocą następujących wskazówek, jeśli nie mamy funkcji optymalizacji obrazu w naszej witrynie:

  1. Nie zezwalaj użytkownikom na bezpośrednie przesyłanie z edytora tekstu, przekierowując ich do galerii obrazów. Na tej stronie użytkownicy muszą przesłać plik z wyprzedzeniem, zanim będą mogli osadzić w treści. Ta metoda jest nazywana menedżerem plików.

  2. Użyj funkcji przycinania obrazu, aby użytkownicy mogli przesyłać obrazy. Ograniczy to rozmiar obrazu, nawet jeśli użytkownicy przesyłają bardzo duże pliki. Ostateczny obraz jest wynikiem przycięcia obrazu. Możemy zdefiniować rozmiar po stronie serwera i zaakceptować tylko na przykład 500Kb lub mniej.

To jest tylko tymczasowe. W celu ostatecznego rozwiązania pytanie powtarza się:

  • Jak radzić sobie z przechowywaniem dużych obrazów?
  • Zmień rozmiar lub zmień rozszerzenie.
  • W jaki sposób duża lub średnia witryna lub handel elektroniczny obsługuje przechowywanie plików obrazów?

Co możemy wtedy zrobić:

  1. Migracja z udostępniania hostingu VPS. Niewystarczająco? Następnie wyższy dzięki aktualizacji do Dedykowany.

  2. Utwórz własny serwer do przechowywania plików. Googlowanie, żeby to zrobić. To nie jest tak trudne, jak myślisz. Niektórzy robią to dla swojej strony internetowej.

  3. Najłatwiejszym sposobem jest skorzystanie z usługi przechowywania plików CDN.

Dobra, 1 i 2 jest trochę drogie. Ale myślę, że nr 3 to najlepsze rozwiązanie.

Niektóre usługi CDN umożliwiają przechowywanie dowolnej liczby plików internetowych.

Pytanie „jak przesłać plik do CDN z naszej strony internetowej?”

Nie martw się, po rejestracji, zwykle bezpłatnej, otrzymasz wskazówki, jak przesłać plik i uzyskać link z / do Twojej witryny. Otrzymasz API i nie tylko. To jest łatwe.

Niektórzy dostawcy zapewniają nam bezpłatną usługę przez 14 dni z ograniczoną pamięcią masową i przepustowością. Ale to wystarczy na początek. Jedynym problemem jest to, że „ludzie nigdy nie próbują”.

Mam nadzieję, że to pomoże nowicjuszowi.

Sulung Nugroho
źródło
13

Klienci nalegali na opcję B (przechowywanie bazy danych) kilka razy na kilku różnych backendach i zawsze końcu do opcji A (pamięć systemu plików).

Takie duże obiekty BLOB po prostu nie były obsługiwane wystarczająco dobrze, nawet przez SQL Server 2005, który jest ostatnim, na którym go wypróbowaliśmy.

W szczególności widzieliśmy poważne wzdęcia i myślę, że mogą problemy z blokowaniem.

Jeszcze jedna uwaga: jeśli korzystasz z pamięci masowej opartej na systemie plików NTFS (serwer Windows itp.), Możesz rozważyć znalezienie sposobu na umieszczenie tysięcy plików w jednym katalogu. Nie wiem dlaczego, ale czasami system plików nie radzi sobie dobrze z taką sytuacją. Jeśli ktoś wie więcej na ten temat, bardzo chciałbym to usłyszeć.

Ale zawsze staram się używać podkatalogów, aby trochę zepsuć. Data utworzenia często sprawdza się w tym przypadku:

Obrazy / 2008/12/17 / .jpg

... Zapewnia to przyzwoity poziom separacji, a także pomaga trochę podczas debugowania. Eksplorator i klienci FTP mogą się nieco dusić, gdy katalogi są naprawdę ogromne.

EDYCJA: Tylko krótka uwaga na rok 2017, w nowszych wersjach SQL Server są nowe opcje obsługi wielu obiektów BLOB, które mają uniknąć wad, które omówiłem.

EDYCJA: Szybka uwaga na rok 2020, Blob Storage w AWS / Azure / etc jest również opcją od lat. Jest to świetne rozwiązanie dla wielu projektów internetowych, ponieważ jest tanie i często może uprościć niektóre problemy związane z wdrażaniem, skalowaniem do wielu serwerów, debugowaniem innych środowisk, gdy jest to konieczne itp.

Brian MacKay
źródło
4
Dobre ostrzeżenie o liczbie plików w tym samym katalogu. Może powodować błędy, które są zbyt trudne do znalezienia w środowisku produkcyjnym.
digao_mb,
1
Już wcześniej napotkałem ten problem. NTFS zachowywał się nieprzewidywalnie z około 10 000 plikami w folderze.
Faiz
1
Nie tylko NTFS, ale także BTRFS, który również ma problem z obsługą ogromnych ilości obrazów w jednym folderze. Mianowicie, gdybyś spróbował ls, zajęłoby to wieczność (zawiesza się). Lub usuń.
sunapi386
11

Niedawno stworzyłem aplikację PHP / MySQL, która przechowuje pliki PDF / Word w tabeli MySQL (do tej pory aż 40 MB na plik).

Plusy:

  • Przesłane pliki są replikowane na serwer kopii zapasowych wraz ze wszystkim innym, nie jest wymagana osobna strategia tworzenia kopii zapasowych (spokój).
  • Konfiguracja serwera WWW jest nieco prostsza, ponieważ nie muszę mieć folderu przesyłania / przesyłania i informować wszystkich moich aplikacji, gdzie on się znajduje.
  • Mogę używać transakcji do edycji, aby poprawić integralność danych - nie muszę się martwić o osierocone i brakujące pliki

Cons:

  • mysqldump zajmuje teraz dłuuuugi czas, ponieważ w jednej z tabel znajduje się 500 MB danych pliku.
  • Ogólnie niezbyt wydajna pamięć / procesor w porównaniu z systemem plików

Moje wdrożenie nazwałbym sukcesem, dba o wymagania dotyczące kopii zapasowych i upraszcza układ projektu. Wydajność jest odpowiednia dla 20-30 osób korzystających z aplikacji.

za dużo php
źródło
6

Używam przesłanych zdjęć na mojej stronie i zdecydowanie powiedziałbym opcję a).

Jeszcze jedną rzeczą, którą gorąco polecam, jest natychmiastowa zmiana nazwy pliku z tego, co użytkownik nazwał zdjęcie, na coś łatwiejszego w zarządzaniu. Na przykład coś z datą i godziną, aby jednoznacznie zidentyfikować każde zdjęcie.

Pomaga również usunąć z nazwy pliku użytkownika wszelkie dziwne znaki, aby uniknąć przyszłych komplikacji.

barfoon
źródło
6

Zdecydowanie zmień rozmiar obrazu i, jeśli możesz, sprawdź jego format. Zdarzały się przypadki przesyłania i udostępniania złośliwych plików przez nieświadome hosty - na przykład GIFAR luka pozwalała na ukrycie złośliwego apletu java w pliku GIF, który byłby następnie w stanie odczytać pliki cookie w bieżącym kontekście i wysłać je do inna witryna do ataku typu cross-site scripting. Zmiana rozmiaru obrazów zwykle temu zapobiega, ponieważ blokuje osadzony kod. Chociaż ten atak został naprawiony przez łatki JVM, naiwne udostępnianie plików binarnych bez ich czyszczenia otwiera Cię na cały szereg luk w zabezpieczeniach.

Pamiętaj, że większość skanerów antywirusowych może działać tylko na systemie plików - jeśli przechowujesz pliki binarne w DB, nie będziesz w stanie łatwo uruchomić skanera przeciwko nim.

Tim Howland
źródło
4

Istnieje coś w rodzaju hybrydowego podejścia w SQL Server 2008, zwanego typem danych strumienia plików , o którym mówiono w RunAs Radio # 74 , które jest jakby najlepszym z obu światów. Większość ludzi nie ma opcji 2008, ale jeśli tak, ta opcja wygląda całkiem fajnie

Charles Graham
źródło
4

W zasadzie to robię.

  1. Przechowuj przesłany obraz w tymczasowym katalogu lub pamięci.
  2. Przetwórz ten obraz przed jego trwałym zapisaniem. 2.1. Korekty kolorów 2.2. Kompresuj 2.3. Utwórz kilka kopii na podstawie wymiarów obrazu. 2.4. Zmień nazwę, dodając przyrostki .xl, .lg, .md, .sm itp
  3. Spakuj wszystkie przetworzone pliki obrazów (z jednego pliku) do folderu o nazwie folderu, idktóra będzie przechowywana w bazie danych dla dowolnego wiersza / dokumentu wraz z image file name(lub może mieć losową nazwę jako nazwę obrazu).
  4. Utwórz folder rrrr / mm / d, path jeśli nie istnieje. Na przykład 2016/08/21. Zapamiętaj tę ścieżkę i przechowuj w bazie danych dla tego samego dokumentu i wiersza.
  5. Przenieś idfolder obrazów do pathfolderu. (Folder Path może znajdować się w folderze / var / web-content).
  6. Opróżnij bufor pamięci lub usuń plik tymczasowy.

Kiedy potrzebujesz uzyskać dostęp do dowolnego obrazu wymienionego w dokumencie, masz ścieżkę i identyfikator folderu, który zawiera obrazy. Na przykład/var/web-content/{{path}}/{{id}}/image-file-name.sm.jpg

W ten sposób, jeśli musisz usunąć wszystkie przetworzone pliki obrazów, po prostu usuń folder i jego zawartość rekurencyjnie.

Uday Hiwarale
źródło
3

Większość implementacji to opcja A.

Z opcją B, otwierasz całą dużą puszkę whoop4ss, kiedy kierujesz te bity z bazy danych do czegoś, co można wyświetlić w przeglądarce ... Ponadto, jeśli baza danych jest wyłączona, obrazy nie są dostępne.

Nie sądzę, żeby przestrzeń była zbyt dużym problemem ... Dyski terabajtowe kosztują teraz kilkaset dolarów.

Wdrażamy opcję A, ponieważ nie mamy czasu ani zasobów na wykonanie opcji B.

mson
źródło
3

W przypadku automatycznej zmiany rozmiaru spróbuj imagemagick ... jest używany w wielu głównych systemach zarządzania treścią / zdjęciami typu open source ... i uważam, że są dla niego pewne rozszerzenia .net.

jle
źródło
2

Używamy A. Umieściłbym to na dysku współdzielonym (chyba że nie planujesz uruchamiać więcej niż jednego serwera).

Jeśli nadejdzie czas, kiedy to nie będzie dla Ciebie skalowalne, możesz zbadać mechanizmy buforowania.

csexton
źródło
2

Absolutnie, pozytywnie opcja A. Inni wspominali, że bazy danych generalnie nie radzą sobie dobrze z obiektami BLOB, niezależnie od tego, czy są do tego zaprojektowane, czy nie. Z drugiej strony systemy plików żyją dla tych rzeczy. Masz możliwość korzystania z rozłożenia RAID, rozpowszechniania obrazów na wielu dyskach, a nawet rozpraszania ich na różnych geograficznie serwerach.

Kolejną zaletą jest to, że tworzenie kopii zapasowych / replikacja bazy danych byłoby potworne.

dj_segfault
źródło
2

Ze względów bezpieczeństwa najlepszą praktyką jest również unikanie problemów spowodowanych przez wykrywanie treści w IE, co może umożliwić atakującym przesyłanie kodu JavaScript do plików graficznych, które mogą zostać wykonane w kontekście Twojej witryny. Więc możesz chcieć jakoś przekształcić obrazy (przyciąć / zmienić ich rozmiar) przed ich przechowywaniem, aby zapobiec tego rodzaju atakom. Ta odpowiedź ma kilka innych pomysłów.

Dzień
źródło
2

Cóż, mam podobny projekt, w którym użytkownicy przesyłają pliki na serwer. Z mojego punktu widzenia opcja a) jest najlepszym rozwiązaniem, ponieważ jest bardziej elastyczna. To, co musisz zrobić, to przechowywać obrazy w chronionym folderze sklasyfikowanym według podkatalogów. Główny katalog musi być ustawiony przez administratora, ponieważ zawartość nie może uruchamiać skryptów (bardzo ważne) i zabezpieczona (odczyt, zapis), aby nie była dostępna w żądaniu http.

Mam nadzieję, że to Ci pomoże.

domoindal
źródło
1

Jeśli są to małe pliki, których nie trzeba edytować, opcja B nie jest złą opcją. Wolę to od pisania logiki do przechowywania plików i radzenia sobie z szalonymi problemami ze strukturą katalogów. Mając dużo plików w jednym katalogu jest złe. emkay?

Jeśli pliki są duże lub wymagają ciągłej edycji, szczególnie z programów takich jak Office, najlepszym rozwiązaniem jest opcja A.

W większości przypadków jest to kwestia preferencji, ale jeśli wybierzesz opcję A, po prostu spraw, aby katalogi nie zawierały zbyt wielu plików. Jeśli wybierzesz opcję B, umieść tabelę z danymi BLOB w swojej własnej bazie danych i / lub grupie plików. Pomoże to w utrzymaniu, zwłaszcza przy tworzeniu kopii zapasowych / przywracaniu. Twoje zwykłe dane są prawdopodobnie dość małe, podczas gdy dane obrazu będą z czasem ogromne .

Charles Graham
źródło
1

Zależy to od Twoich wymagań, w szczególności ilości, użytkowników i częstotliwości wyszukiwania. Jednak w przypadku małego lub średniego biura najlepszą opcją jest użycie aplikacji takiej jak Apple Photos lub Adobe Lighroom. Specjalizują się w przechowywaniu, katalogowaniu, indeksowaniu i organizowaniu tego rodzaju zasobów. Jednak w przypadku dużych organizacji z dużymi wymaganiami dotyczącymi pamięci masowej i dużą liczbą użytkowników zaleca się utworzenie instancji platformy zarządzania treścią z zarządzaniem zasobami cyfrowymi, np. Nuxeo lub Alfresco; oba oferują bardzo dobre zasoby, zarządzają bardzo dużymi ilościami danych przy użyciu uproszczonych metod ich pobierania. I bardzo ważne: istnieje bezpłatna (open source) opcja dla obu platform.

Carlos Camargo
źródło