Upload di un file

20 views
Skip to first unread message

diego.benna

unread,
Aug 20, 2009, 10:15:49 AM8/20/09
to Parancoe-users
Ciao a tutti,
mi sto imbattendo in un nuovo problema in parancoe:
sto cercando di fare l'upload di file in un DB (sto usando mysql)

La mia classe entita' e' questa:

@javax.persistence.Entity()
public class Publication extends EntityBase {

@NotBlank
private String description;

@NotBlank
private File file; // ho messo il tipo file

public Publication() {
}

... get and set..
}


La funzione di save nel controller e' questa (un normale store):

@RequestMapping
public String save(@ModelAttribute(PUBLICATION_ATTR_NAME)
Publication publication,
BindingResult result, SessionStatus status) {
publicationDao.store(publication);
status.setComplete();
return "redirect:edit.html";
}


Il mio form nella pagina jsp e' questo:

<form:form enctype="multipart/form-data" commandName="publication"
method="POST" action="${cp}/publication/save.form">
<table>
<tr>
<td>Description:</td>
<td><form:input path="description"/></td>
</tr>
<tr>
<td>File:</td>
<td>
<spring:bind path="file">
<input id="file" name="file"
type="file">
</spring:bind>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="submit" value="Submit"/
><br/><br/></td>
</tr>
</table>
<form:errors path="*" cssClass="errorBox"/>
</form:form>

Cosi' facendo la descrizione viene salvata ma non il file scelto. Se
invece sostituisco
<spring:bind path="file">
<input id="file" name="file" type="file">
</spring:bind>

con un semplice campo di inserimento:
<form:input path="file"/> e aggiungo il path corretto del mio pdf, nel
database mi ritrovo un dato di soli 119kb (segnato con tipo Blob)
contro il circa 1 MB e mezzo del file pdf. Cosa significa?
Sapete per favore dirmi come e' possibile fare l'upload e il download
di un file da DB con parancoe per favore?
Grazie mille e scusate il disturbo

Diego

Lucio Benfante

unread,
Aug 20, 2009, 3:27:12 PM8/20/09
to paranco...@googlegroups.com
Ciao Diego,
è abbastanza semplice...ma bisogna usare i tipi giusti e configurare il
controller di conseguenza.

Nell'entity usa un array di byte:

@javax.persistence.Entity()
public class Publication extends EntityBase {

@NotBlank
private String description;

@NotBlank
private byte[] file;

public Publication() {
}

... get and set..
}


Nel controller bisogna definire il binding corretto per il tipo byte[]
definendo nel controller un metodo come il seguente:

@InitBinder
protected void initBinder(WebDataBinder binder) throws Exception {
binder.registerCustomEditor(byte[].class,
new ByteArrayMultipartFileEditor());
}

Il metodo save invece andava bene.

Il campo per il file nella JSP è banalmente:

<input type="file" name="publication.file"/>

(ma anche come hai fatto tu, con lo spring:bind, dovrebbe andare bene)

Ultima osservazione sulla dimensione dei file da uploadare. Di default
parancoe ha una configurazione con un limite ad 1MB. Se è necessario
permettere l'upload di file di dimensioni maggiori, occorre aggiungere
la seguente configurazione nel parancoe-servlet.xml:

<bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- the maximum file size in bytes -->
<property name="maxUploadSize" value="1000000"/>

</bean>

Ciao
Lucio

--
Lucio Benfante
JUG Padova http://www.parancoe.org ...have a look at it!
www.jugpadova.it http://www.jugevents.org


Diego Benna

unread,
Aug 21, 2009, 6:25:11 AM8/21/09
to paranco...@googlegroups.com
Ciao Lucio,
grazie mille per la risposta, sei gentile come sempre! Grazie al tuo aiuto ora ho risolto il problema!! Grazie ancora!

Ho un'ultimissimo aiutino da chiederti :) Ora mi trovo nella situazione di fare il download del file: come faccio a recuperare il file? che link creo?

questo e' il codice in list.jsp dove visualizzo i file.

<c:forEach var="publication" items="${publication}">
                            <tr>
                                <td>${publication.file}</td>
                                <td>${publication.description}</td>
                                <authz:authorize ifAnyGranted="ROLE_ADMIN">
                                    <td>
                                        <a href="edit.form?id=${publication.id}">Edit</a>
                                        <a href="delete.html?id=${publication.id}">Delete</a>
                                    </td>
                                </authz:authorize>
                            </tr>
                        </c:forEach>

mi visualizza cose del tipo:

[B@1a0f6dd 
[B@af3556 
[B@d6d4be
[B@291bea
[B@e7e05b
[B@13a959a
[B@133bf6d
[B@135c14f


suppongo sia la conversione in Unicode dei primi byte del file. Quindi non posso usare <a href="${publication.file}">${publication.file}</a>. Non ha nemmeno senso.. e neanche come nome del file [B@1a0f6dd non ha senso. Ho provato a cercare in internet come recuperare il file dal campo blob (per creare il link) ma non trovo nulla :(

Spero di non disturbarvi troppo nel chiedervi continui aiuti
Grazie mille

Diego

Lucio Benfante

unread,
Aug 21, 2009, 10:26:39 AM8/21/09
to paranco...@googlegroups.com
Diego Benna ha scritto:

>
> Ho un'ultimissimo aiutino da chiederti :) Ora mi trovo nella
> situazione di fare il download del file: come faccio a recuperare il
> file? che link creo?
> [cut]

> mi visualizza cose del tipo:
>
> [B@1a0f6dd

[cut]


>
> suppongo sia la conversione in Unicode dei primi byte del file.

No, quello è la rappresentazione del reference all'oggetto array di bye.

Sostanzialmente quello che devi fare tu è spedire i byte sull'output
stream della risposta.

Crei un metodo nel tuo controller, ad esempio:

@RequestMapping
public void download(@RequestParam("id") Long id, HttpServletRequest
req,
HttpServletResponse res) throws Exception {
Publication publication = publicationDao.get(id);
OutputStream out = null;
try {
out = res.getOutputStream();
res.setContentType("application/pdf");
res.setContentLength(publication.getFile().length);
res.setHeader("Content-Disposition",
" attachment; filename=\"publication.pdf\"");
res.setHeader("Expires", "0");
res.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
res.setHeader("Pragma", "public");
out.write(publication.getFile());
out.flush();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
}
}
}
}


Nell'esempio ipotizzo che siano PDF, se sono altro devi aggiustare il
ContentType e l'estensione di conseguenza.

Il link sarà qualcosa del tipo:

<a href="download.html?id=${publication.id}">download</a>

Reply all
Reply to author
Forward
0 new messages