venerdì 24 ottobre 2008

Upload di file

Per effettuare l'upload di un file sul server è necessario utilizzare le Commons FileUpload API (http://commons.apache.org/io) e le Commmons IO API (http://commons.apache.org/fileupload); le prime forniscono un meccanismo semplice, robusto e performante di upload di file ad un'applicazione web, le seconde un supporto allo sviluppo di funzionalità Input-Output e ci serviranno per memorizzare i file uplodati sul server.

La form che ci permetterà di selezionare un file lato client sarà del tipo:

<form action="UploadFile" method="post" enctype="multipart/form-data" accept="image" maxlength="100000">
<input type="file" name="fileUploaded"/>
<input type="submit" value="Send"/>
</form>

in cui l'attributo accept permette di filtrare il tipo di file uplodato e maxlength di specificarne la grandezza in byte massima. La servlet che processerà la richiesta sarà UploadFile la quale si aspetta, tramite richiesta POST, un parametro con nome fileUploaded. All'interno della servlet UploadFile inseriamo il seguente codice:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
ServletRequestContext src=null;
src = new ServletRequestContext(request);
if (FileUpload.isMultipartContent(src)){
DiskFileItemFactory dfif=null;
ServletFileUpload fu = null;
String path = "/upload/";
File file = new File(path);
if (!file.exists())
file.mkdirs();
dfif = new DiskFileItemFactory(size,file);
fu = new ServletFileUpload(dfif);
List itemList = null;
try{
itemList = fu.parseRequest(src);
}catch(Exception e){
response.sendError(500,e.getMessage());
return;
}
HashMap<String, FileItem> files
= getFileParameters(itemList);
FileItem fItem = files.get("fileUploaded");
String mime = fItem.getContentType();
int extIndex = mime.length()-3;
String ext = "."+mime.substring(extIndex);
String fileStr = fItem.getFieldName()+ext;
try{
fItem.write(new File(path+fileStr));
}catch(Exception e){
response.sendError(500, e.getMessage());
}
request.setAttribute("msg", "Upload OK");
}
RequestDispatcher rDisp;
ServletContext sc = this.getServletContext();
rDisp = sc.getRequestDispatcher("/info.jsp");
rDisp.forward(request, response);
}
/*
* estrae i FileItem della form e li
* inserisce in una Map in cui le chiavi
* sono i nomi dei parametri
*/
private HashMap<String, FileItem> getFileParameters(List itemList){
HashMap<String, FileItem> ret
= new HashMap<String, FileItem>();
Iterator iter = itemList.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (!item.isFormField()){
String fieldName = item.getFieldName();
ret.put(fieldName, item);
}
}
return ret;
}

Il metodo private HashMap<String, FileItem> getFileParameter(List itemList) in questo caso è poco utile, trattandosi dell'upload di un solo file, ma in genere permette di trattare i parametri di tipo non-FormField (quelli che contengono i file da uploadare) alla stregua dei classici parametri testuali, i quali possono essere inviati al server secondo un ordine non predefinito. I parametri non-FormField vengono inviati al server secondo l'ordine con cui vengono dichiarati nella form per cui una modifica della form potrebbe voler richiedere una modifica nella servlet.
Utilizzando HashMap<String, FileItem> il problema viene aggirato in quanto si fa riferimento ai vari FileItem di tipo non-FormField in base ai nomi e non alla posizione che occupano nella form.

ATTENZIONE: quando l' enctype definito nella form è multipart/form-data anche i tradizionali parametri testuali devono essere prelevati nella servlet usando la tecnica dell' HashMap ( con l'istruzione tradizionale request.getParameter("nomeparametro") il valore restituito è sempre null):

/*
 * estrae i parametri testuali della form e li
inserisce in una Map in cui le chiavi sono i nomi dei parametri
*/
private HashMap<String, String> getStringParameters(List
itemList){
    HashMap<String, String> ret = new HashMap<String, String>();
    Iterator iter = 
itemList.iterator();
    while (iter.hasNext()) {
        FileItem item = (FileItem) iter.next(); 
        if (item.isFormField()){
            String fieldName = item.getFieldName();
            String fieldValue = item.getString();
            ret.put(fieldName, fieldValue);
        }
     }
    return ret;
}

il valore di un parametro sarà prelevato attraverso la seguente istruzione:

....
HashMap<String, String> uploadedParameters = getStringParameters(itemList);
String parameterValue =  uploadedParameters.get("parameterName");
...

Alcuni IDE, per esempio Netbeans, permettono di aggiungere in maniera molto semplice un componente per l'uload di file in un applicazione JSF Visual Web (http://www.netbeans.org/kb/60/web/fileupload.html).

Nessun commento: