zapisanie pliku BLOB w bazie danych

0

czesc,

probuje w aplikacji webowej dodac plik do bazy danych poprzez Hibernate'a i nie moge. Mam w kontrolerze cos takiego:

 
@RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addEmployee(@ModelAttribute(value="employee") EmployeeEntity employee, @RequestParam("file") MultipartFile file, BindingResult result)
    {
    	Blob blob = Hibernate.getLobCreator(sessionfactory.getCurrentSession()).createBlob(file.getInputStream());
    	
        employee.setContent(content);
    	
        employeeManager.addEmployee(employee);
        return "redirect:/baza";
    }

a encja wyglada tak:

 
@Column(name="CONTENT")
    @Lob
    private Blob content;
    
    public Blob getContent() {
		return content;
	}
	public void setContent(Blob content) {
		this.content = content;
	}

To jest oczywiscie zle i wiem ze cos jest zle z argumentem w getLobCreator ale nie wiem za bardzo co tam przywolac i jak to zgrac, on tam chce Session session. Tak kombinuje z tym i mysle, pomozecie co tu zrobic? Zaleznosci raczej dodane prawidlowo, w widoku tez dobrze, w bazie chyba tez, mysle ze tu jest problem ale jak cos to moge zapodac kod innych plikow. Prosze o pomoc.

0

to jak? pomoze ktos?

0

Jakiś komunikat o błędzie czy coś?

0

@Koziołek w tej wersji co wkleilem wczesniej nie czail skad sie wzielo sessionfactory. To ok, zrobilem Autowired i zapodalem mu cos takiego:

 
@RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addEmployee(@ModelAttribute(value="employee") EmployeeEntity employee, @RequestParam("file") MultipartFile file, BindingResult result) throws IOException
    {
    	Session session = this.sessionFactory.getCurrentSession();
    	
    	Blob blob = Hibernate.getLobCreator(session).createBlob(file.getInputStream(),4);
    	
        employee.setContent(blob);
    	
        employeeManager.addEmployee(employee);
        return "redirect:/baza";
    }

tu nie widzi zadnego bledu, ta cyfre 4 dalem tam z d**y zeby sie nie czepial o blad (dalem tam tez file.getSize() - efekt ten sam), nie widzi bledu ale przy probie zapisu do bazy wyrzuca wyjatek:

 
Failed to convert value of type 'java.lang.String' to required type 'org.springframework.web.multipart.MultipartFile'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [org.springframework.web.multipart.MultipartFile]: no matching editors or conversion strategy found

Jesli usune stamtad ta cyfre 4 i nie wstawie nic to znowu nie przepusci mi i bedzie krzyczal ze:

The method createBlob(byte[]) in the type LobCreator is not applicable for the arguments (InputStream)
 

co tu jest grane???

0

To że nie rozumiesz co robisz? Twój błąd z createBlob wynika z tego że nie czytasz dokumentacji i nie rozumiesz co oznaczają argumenty metody. Polecam poczytać.
Drugi błąd, ten z multipart file, to jest zupełnie inna bajka. To jest błąd przesyłania obiektu przez Springa z formularza do kontrolera i nie ma NIC wspólnego z twoją bazą, Hibernate ani niczym z tej serii. Po prostu z formularza leci ci string a nie żaden file. Poka ten formularz.

0

@Shalom, ok rozumiem o co ci chodzi, faktycznie, brakowalo w formularzu

 
enctype="multipart/form-data"

uzupelnilem to ale mam inny problem. Teraz przy probie zapisu do bazy mam wyjatek:

Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'

Mysle ze bierze sie on z tego ze w kontrolerze wrzucilem to

Session session = this.sessionFactory.getCurrentSession();

wczesniej jak nie mialem dodawania pliku do bazy to wszystko smigalo. Konta sa autoryzowane przez Spring Security.
Jak teraz przywrocic zeby z powrotem ochrona CSRF smigala?

0

Nie nie nie. Błąd znów nie ma NIC wspólnego z hibernate ani z żadnymi sesjami tylko ze spring security. Patrz tu:
http://stackoverflow.com/questions/21514074/spring-csrf-token-does-not-work-when-the-request-to-be-sent-is-a-multipart-requ
jak przesyłasz coś jako multipart to spring musi to odpowiednio obsłużyć żeby spring security zadziałało i dodało poprawnie token csrf

0

@Shalom, @Koziołek, ok poprawilem web.xml i teraz wyglada tak:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

<servlet>
    <servlet-name>student-recruitment-app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>student-recruitment-app</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
 
        <!-- Loads Spring Security config file -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-security.xml
			/WEB-INF/student-recruitment-app-servlet.xml
		</param-value>
	</context-param>
 
	<!-- Spring Security -->
	<filter>
        <filter-name>MultipartFilter</filter-name>
        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    </filter>
	
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy
		</filter-class>
	</filter>
 	
 	<filter-mapping>
        <filter-name>MultipartFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
</web-app>
 

tylko teraz tez nie moge zapisac bo znowu cos nie tak z tym multipartem bo wyrzuca mi wyjatek:

HTTP Status 500 - Filter execution threw an exception

type Exception report

message Filter execution threw an exception

description The server encountered an internal error that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Filter execution threw an exception

root cause

java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.getParts()Ljava/util/Collection;
	org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:84)
	org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:77)
	org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:76)
	org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:108)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

 

szukalem na google ale nie za bardzo wiem co jest zle, na pewno to cos banalnego ale ciezko mi zidentyfikowac hdzie lezy blad.

0

Musisz użyć Servlet API w wersji 3.0 a nie 2.5 tak jak teraz. To znaczy że musisz zmienić wersje w mavenie albo zmienić kontener servletów na nowszy (zalezy jak to robisz).

0

@Shalom, zmienilem Tomcata na 7.0 i pojawia sie problem znowu z CSRF. Wyczytalem tu ze sa 2 opcje jego konfiguracji:
http://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html#csrf-multipartfilter

wybieram pierwsza i ustawiam tak w web.xml (tak jak wczesniej), moze ja mam cos zle w formularzu w stronie jsp?

to jej kluczowy fragment, moze tam czegos zapomnialem?

 
<form:form method="post" action="add" commandName="employee" enctype="multipart/form-data">
        <table>
        <tr>
            <td><form:label path="firstname"><spring:message code="label.firstname"/></form:label></td>
            <td><form:input path="firstname" /></td>
        </tr>
        <tr>
            <td><form:label path="lastname"><spring:message code="label.lastname"/></form:label></td>
            <td><form:input path="lastname" /></td>
        </tr>
        <tr>
            <td><form:label path="email"><spring:message code="label.email"/></form:label></td>
            <td><form:input path="email" /></td>
        </tr>
        <tr>
            <td><form:label path="telephone"><spring:message code="label.telephone"/></form:label></td>
            <td><form:input path="telephone" /></td>
        </tr>
        <tr>
            <td><form:label path="pesel"><spring:message code="label.pesel"/></form:label></td>
            <td><form:input path="pesel" /></td>
        </tr>
        <tr>
            <td><form:label path="content"><spring:message code="label.content"/></form:label></td>
            <td><input name="file" id="file" type="file"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="<spring:message code="label.add"/>"/>
            </td>
        </tr>
    </table> 
    
    </form:form>

a to blad z CSRF:

 
HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

type Status report

message Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

description Access to the specified resource has been forbidden.
Apache Tomcat/7.0.57
0

Na oko powinno być ok. Jesteś pewien że uruchamiasz to z tym poprawnym web.xml?

0

@Shalom, moj web.xml wyglada dokladnie tak:

 
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">


<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-security.xml
			/WEB-INF/student-recruitment-app-servlet.xml
		</param-value>
	</context-param>
<servlet>
    <servlet-name>student-recruitment-app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>student-recruitment-app</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener
		</listener-class>
	</listener>
 
	<!-- Spring Security -->
	<filter>
        <filter-name>MultipartFilter</filter-name>
        <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    </filter>
	
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy
		</filter-class>
	</filter>
 	
 	<filter-mapping>
        <filter-name>MultipartFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	
</web-app>
0

@Shalom, ok wylaczylem na chwile ochrone CSRF i przy zapisie dostaje blad:

Required MultipartFile parameter 'file' is not present
 

a wiec cos jest zle z przesylaniem z formularza do kontrolera.
to moj kontroler odpowiedzialny za request przy zapisie do bazy:

 
@RequestMapping(value = "/add", method = RequestMethod.POST)
    public String addEmployee(@ModelAttribute(value="employee") EmployeeEntity employee, @RequestParam("file") MultipartFile file, BindingResult result) throws IOException
    {
    	Session session = this.sessionFactory.getCurrentSession();
    	
    	Blob blob = Hibernate.getLobCreator(session).createBlob(file.getInputStream(),file.getSize());
    	
        employee.setContent(blob);
    	
        employeeManager.addEmployee(employee);
        return "redirect:/baza";
    }

w nazwa_aplikacji-servlet.xml dodalem oczywiscie:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
       <property name="maxUploadSize" value="-1"/> <!-- File size in bytes. -->
</bean> 
 

web.xml a takze strone jsp juz wrzucalem wczesniej, co tu moze byc zle z przesylaniem do kontrolera?

0

Nie, po prostu ty nadal nie rozumiesz kodu który wklejasz. Mam radę: nie umieszczaj ani jednej linijki kodu której nie rozumiesz. W tym przypadku jest to:
@RequestParam("file") którego ewidentnie nie rozumiesz bo w twoim przypadku w ogóle tego być nie powinno...

0

OK z tego co widze możesz to sobie tak podzielić, więc kontroler może zostać tak jak byl z tym @RequestParam ale potrzebny ci jest bean
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

0

Podepnę się pod temat i zapytam z innej beczki - lepiej ogółem obsłużyć wysyłanie w ten sposób, że plik jest zapisywany na serwerze i do bazy leci tylko jego ścieżka czy ładować cały plik do bazy?

1

@hcubyc zależy od ilości danych (baza za dużych plików nie lubi łykać) i też jak potem chcesz tego używać.

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