Zapisywanie avatarów użytkowników w bazie MySQL jako url do jakiego adresu?

0

Mam sobie stronę w jsp a oto jej fragment:

			<div class="about_user">
				<img src="${sessionScope.user.avatar }" />
				<p>Login: ${sessionScope.user.login}</p>
				<p>Imię: ${sessionScope.user.name}</p>
				<p>Nazwisko: ${sessionScope.user.surname}</p>
				<p>Data urodzenia: ${sessionScope.user.birthDate}</p>
				<p>Adres zamieszkania: ${sessionScope.user.address}</p>
				<p>Adres e-mail: ${sessionScope.user.email}</p>
				<p>Data rejestracji: ${sessionScope.user.registerDate}</p>
				<p>
					Utworzone posty -
					<c:forEach var="userThread" items="${userThreads}">
						<p>userThread.topic</p>
					</c:forEach>
				</p>
			</div>

Jak widać potrzebuję tu wyświetlać informacje o zarejestrowanym wcześniej i aktualnie zalogowanym użytkowniku który jest trzymany w sesji, pole "avatar" encji user to adres url jego zdjęcia profilowego. Mam jednak dylemat gdzie zapisywać to zdjęcie, nie mogę przecież lokalnie u siebie na dysku np w /tmp/images/ albo /home/moja_nazwa_uzytkownika/images, bo później przy wyświetleniu jest problem, do adresu dodaje się localhost:8080/tmp/images/adam123.jpg lub localhost:8080/home/moja_nazwa_uzytkownika/home/adam123.jpg zamiast szukać go na dysku szuka na serwerze tomcat. Rozwiązaniem problemu mogłoby się wydawać zapisanie tego w jednym z katalogów/podkatalogów projektu jak np /WebContent/images/adam123.jpg ale nie mogę tam zapisać nie wiem dlaczego.

Formularz rejestracja.jsp

		<div id="c_center">
			<div class="c_header">REJESTRACJA</div>
			<span style="color: red; font-size: 12px; letter-spacing: 1px;"><p>${error}</p></span>
			<form action="" method="post" enctype="multipart/form-data">
				<div class="registerLeft">
					<p>Imię:</p>
					<input name="firstName" />
					<p>Nazwisko:</p>
					<input name="lastName" />
					<p>Adres zamieszkania:</p>
					<input name="address" />
					<p>Data urodzenia:</p>
					<input type="date" name="birthDate">
				</div>
				<div class="registerRight">
					<p>Login:</p>
					<input name="login" />
					<p>Hasło:</p>
					<input type="password" name="password" />
					<p>Hasło (ponownie):</p>
					<input type="password" name="retypePassword" />
					<p>Adres e-mail:</p>
					<input name="email" />
				</div>
				<br />
				<div class="registerLeft" style="margin-right: 90px">
					<p>Avatar:</p>
					<input type="file" name="file" id="file" style="border: none" />
				</div>
				<div class="registerRight">
					<p>Przepisz kod z obrazka:</p>
					<img src="stickyImg" /><br /> <input name="answer" />
				</div>
				<br /> <input type="submit" value="Zarejestruj"
					class="registerButton" />
			</form>
		</div>

Kluczowy fragment kodu servletu rejstracji użytkownika:

protected void doPost(HttpServletRequest request, HttpServletResponse response){

				if (!uploadRequest(request, response)) {
					doGet(request, response);
					return;
				}

}

A tu fragment servletu rejestracji, wywołanie uploadRequest z metody doPost powyżej

protected boolean uploadRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		String path = "/tmp/";
		Part filePart = request.getPart("file");
		String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
		
		System.out.println(path);

		InputStream in = null;
		FileOutputStream out = null;

		if (!checkFileType(fileName)) {
			request.setAttribute("error", "Niezgodny typ pliku");
			return false;
		}

		try {
			in = filePart.getInputStream();

			if (in.available() > 50000) {
				in.close();
				request.setAttribute("error", "Rozmiar pliku nie może przekraczać 50 kB");
				return false;
			}
			String fullFilePath = path + request.getParameter("login") + "." + getFileExtension(fileName);
			out = new FileOutputStream(new File(fullFilePath));
			int read = 0;
			final byte[] bytes = new byte[1024];
			while ((read = in.read(bytes)) != -1) {
				out.write(bytes, 0, read);
			}
			System.out.println("PATH: " + fullFilePath);
			request.setAttribute("userAvatar", fullFilePath);
		} catch (FileNotFoundException ex) {
			request.setAttribute("error", "Nie wybrałeś pliku lub wybrany plik nie istnieje");
		} finally {
			if (in != null)
				in.close();
			if (out != null)
				out.close();
		}
		return true;
	}

	private boolean checkFileType(String fileName) {
		int errorFileType = 0;
		if (!fileName.endsWith(".png"))
			errorFileType++;
		if (!fileName.endsWith(".jpg"))
			errorFileType++;
		if (!fileName.endsWith(".jpeg"))
			errorFileType++;
		if (errorFileType == 3)
			return false;
		return true;
	}
	
	private String getFileExtension(String fileName) {
		String extension = "";
		
		int i = fileName.lastIndexOf('.');
		if (i > 0) {
		    extension = fileName.substring(i+1);
		}
		return extension;
	}

Próbowałem już stworzyć katalog /WebContent/images i zmienić String path = request.getContextPath() + "/images/" ale to nie pomaga bo obrazek nie zapisuje sie tam a do bazy w miejsce url trafia null

1

W ogóle nie używaj plików. Trzymaj bajty obrazków w bazie danych i serwuj pod linkami typu /avatar/7887823423.jpg. Serwer www musi dekodować te urle i zwracać bajty z bazy danych.

0
jarekczek napisał(a):

W ogóle nie używaj plików. Trzymaj bajty obrazków w bazie danych i serwuj pod linkami typu /avatar/7887823423.jpg. Serwer www musi dekodować te urle i zwracać bajty z bazy danych.

Udało mi się wygóóglować wcześniej to z typem kolumny BLOB w bazie ale nie przekonuje mnie to rozwiązanie:
Nie jest to obciążenie dla bazy trzymać w tabeli 48 kiloBajtowe dane? to tak jakby wpisać tam 48000 znaków;
Druga rzecz, gdybym później chciał przechowywać zdjęcia poglądowe tzw. "threadAvatars" tematów które wyświetlam nad tytułem i datą dodania to musiałbym kolejne dane przechować w bazie

0

Co za różnica w plikach czy w bazie? W pewnych okolicznościach może to mieć znaczenie, ale generalnie - nie ma. Możesz sobie zrobić osobną bazę danych na zdjęcia, może być nierelacyjna. A jeżeli chcesz w plikach, to też możesz. Tylko serwuj je w odpowiedni sposób. Ustal jakiś katalog, a potem tak skonfiguruj serwer, żeby stamtąd je pobierał. Każda platforma (spring boot, apache) oferuje takie możliwości.

Trzymanie zdjęć w bazie ułatwia backup (wszystko w jednym, nie zgubisz zdjęć, łatwo przeniesiesz), a zarazem utrudnia (robi się duży). Normalne dylematy :)

0

Tylko jak się później odwołać do takiego obrazka zapisanego jako plik przy czym w bazie w uzytkowniku jest ścieżka do tego pliku np /tmp/avatar/login1.jpg
aplikacja jest póki co projektem w eclipse więc stamtąd uruchamiany jest tomcat.
W serwlecie nie da się zapisać obrazu w katalogach projektu żeby móc później ustawić atrybut katalogu z avatarami request.setAttribute("url", request.getContextPath() + "/avatar/"); i w widoku strony użytkownika się do niego odwołać.

0

Url do pliku: http://twojastrona.pl/pliki/787878787. Obsługując żadanie pod adresem /pliki/ pobierasz plik skąd chcesz, nie musi to być katalog pliki. Innymi słowy: katalog w urlu, a katalog fizyczny nie muszą być tożsame. Serwer dokonuje mapowania, a Ty to mapowanie konfigurujesz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1