giovedì 20 marzo 2008

Upload e Download File

0 commenti
Per fare l’upload di un file useremo le librerie di struts. Per prima cosa andiamo a creare un form che si occuperà dei metodi accessori per il file che vogliamo salvare che sara di tipo FormFile di struts.


package com.myapp.struts.action;

import org.apache.struts.action.ActionForm;
import org.apache.struts.upload.FormFile;

/**
*
* @author r.sheshi
*/
public class UploadFile extends ActionForm {
private FormFile file;

public FormFile getFile() {
return file;
}

public void setFile(FormFile file) {
this.file = file;
}


}

Dopo aver definito il form creiamo la jsp che si occuperà del upload.



<html:form action="/upload" enctype="multipart/form-data">
<html:file property="file" />
<html:submit value="carica" />
</html:form>



Il form deve avere l’enctype impostato “multipart/form-data” e usa il tag html:file con la propetrty impostata a “file” come mappata nel nostro form. A questo punto andiamo a creare la nostra action.


/**
*
* @author r.sheshi
*/
public class CaricaFileAction extends Action{


@Override
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{

DynaActionForm f =(DynaActionForm) form;
FormFile ff = (FormFile) f.get("file");

return mapping.findForward("success");
}

}

Nella action ci prendiamo il file dal bean che struts ha valorizzato.Dopo aver preso il file bisogna andarlo a inserilo nel nostro campo blob. Pertanto ci creamo un oggetto che si occupera di trasferire i dati dalla action nel Dao che si ocuperà di inserirlo.


/**
*
* @author r.sheshi
*/
public class FileDto {


private int id;
private byte[] bytes;
private int size;
private String name;
private String contentType;


public void setBytes(byte[] bytes) {
this.bytes = bytes;
}

public byte[] getBytes() {
return bytes;
}
public void setId(int id) {
this.id = id;
}

public int getId() {
return id;
}


public void setName(String name) {
this.name = name;
}

public void setSize(int size) {
this.size = size;
}

public void setContentType(String type) {
this.type = type;
}

public String getName() {
return name;
}

public int getSize() {
return size;
}

public String getContentType() {
return type;
}

}


Adesso che abbiamo il nostro Dto che ha un variabile di classe un array di byte che verra valorizzarlo nella action dal FormFile con il metodo getFileData().

DynaActionForm f =(DynaActionForm) form;
FormFile ff = (FormFile) f.get("file");

FileDto dto= new FileDto();
dto.setBytes(ff.getFileData());
dto.setContentType(ff.getContentType());
dto.setSize(ff.getFileSize());
dto.setName(ff.getFileName());


Adesso che abbiamo valorizzato il nostro Dto lo passiamo al dao per inserirlo nel database.


FileDao dao= new FileDao();
dao.insert(dto);


Poi nel FileDao esguiamo le operazioni per l’inseriento nella nostra tabella FILE,che avra 4 campi(ID , FILE (BLOB), NOME(VARCHAR), CONTENT_TYPE(VARCHAR)).



private String INSERT="INSERT INTO FILE VALUES(?,?,?,?)";

public void insert(FileDto dto) {
PreparedStatement ps = null;
Connection con = null;

try {


con = getConnection();
ps = con.prepareStatement(INSERT);
ps.setInt(1, dto.getId);
ps.setBytes(2, dto.getBytes());
ps.setString(3, dto.getName());
ps.setString(4, dto.getContentType());
ps.executeUpdate();
} catch (SQLException ex) {
Logger.getLogger(FileDao.class.getName())
.log(Level.SEVERE, null, ex);
}finally{
try {
if (ps != null) ps.close();
if (con != null)con.close();

} catch (SQLException ex) {
Logger.getLogger(FileDao.class.getName())
.log(Level.SEVERE, null, ex);
}

}
}


A questo punto avremo dentro la tabella il nostro file e tutte le informazioni al riguardo.




Come facciamo a prendere il file quando ci serve?



Adesso che abbiamo i nostri file nel database creiamo una action per visualizzare una lista dei file.
Aggiungiamo un metodo al Dao che fara una select ritornandoci un Arraylist di Dto con valorizzato solo id e il nome.


public ArrayList listaFile() {
PreparedStatement ps = null;
ResultSet rs = null;
Connection con = null;

ArrayList dtos = new ArrayList();
try {


con = getConnection();
ps = con.prepareStatement(SELECT);
rs = ps.executeQuery();
while(rs.next()) {
FileDto dto = new FileDto();
dto.setId(rs.getInt(1));
dto.setName(rs.getString(2));


dtos.add(dto);

}
} catch (SQLException ex) {
Logger.getLogger(FileDao.class.getName())
.log(Level.SEVERE, null, ex);
}finally {
try {
if (rs != null) ps.close();
if (ps != null) ps.close();
if (con != null)con.close();
} catch (SQLException ex) {
Logger.getLogger(FileDao.class.getName())
.log(Level.SEVERE, null, ex);
}
}
return dtos;
}


Poi creiamo una nuova Action che chiamerà il metodo listaFile che avra come ritorno la nostra collection che mettermo in request per poi scorrerla nella jsp.


public class ListaFileAction extends Action{


@Override
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception{

FileDao dao =new FileDao();
ArrayList dtos = dao.listaFile();
request.setAttribute("lista", dtos);
return mapping.findForward("lista");
}

}



Ora che abbiamo la nostra lista visualizziamola nella jsp come una serie di link che al click chiamera una action passandogli id del file per scaricarlo.



<html:html>
<logic:present name="lista" >
<logic:iterate name="lista" id="dto" >

<html:link action="/download" paramId="idFile"
paramName="dto" paramProperty="id">

<bean:write name="dto" property="name" />
</html:link>
</logic:iterate>
</logic:present>
</html:html>



Procediamo nel creare la action che gestisce il download dei file in base all’id che gli passeremo nel link andrà a recuperare il file nel database chiamando il Dao.

private String SELECT_BY_ID="Select * from file where id = ?";
public FileDto findById(int id) {
PreparedStatement ps = null;
ResultSet rs = null;
Connection con = null;
FileDto dto = new FileDto();

try {


con = getConnection();
ps = con.prepareStatement(SELECT_BY_ID);
ps.setInt(1,id);
rs = ps.executeQuery();
while(rs.next()) {
Blob blob = rs.getBlob(2);
byte[] bytes =blob.getBytes(1, (int)blob.length());
dto.setId(rs.getInt(1));
dto.setBytes(bytes);
dto.setName(rs.getString(3));
dto.setContentType(rs.getString(4));




}
} catch (SQLException ex) {
Logger.getLogger(FileDao.class.getName())
.log(Level.SEVERE, null, ex);
}finally {
try {
if (rs != null) ps.close();
if (ps != null) ps.close();
if (con != null)con.close();
} catch (SQLException ex) {
Logger.getLogger(FileDao.class.getName())
.log(Level.SEVERE, null, ex);
}
}
return dto;
}



Dopo aver chiamato il metodo findById() del Dao settiamo nella response il ContentType in base alla tipologia del file. Nel Header settiamo attachment in modo che venga scaricato in locale e il nome del File. Poi Recuperiamo ServletOutputStream e scriviamo l’array di byte.



public class DownloadAction extends Action{


@Override
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception{
FileDao dao =new FileDao();
String id = request.getParameter("idFile");
FileDto dto= dao.findById(Integer.parseInt(id));

response.setContentType(dto.getContentType());
response.setHeader("Content-Disposition",
"attachment;filename=\""+dto.getName()+"\"");

final ServletOutputStream out= response.getOutputStream();
out.write(dto.getBytes());


return null;
}

}