Saturday, March 17, 2012

GWT: Creating a simple File hosting site

GWT : Creating a simple file hosting site


The free hosting site that I used to store my source code was gone without warning.
Thus, I no longer trust these free sites anymore.

To store my android tutorial source code, I decided to create a simple file hosting so I can upload my source codes.
Further, since the app-engine service by google is free I decided to use it.

Tools/Libraries/Framework used:

1. Google App Engine
2. GWT
3. Apache File Upload

Links to get started with Google App Engine (GAE) and Google web Toolkit (GWT)

1. GAE http://code.google.com/webtoolkit/doc/latest/tutorial/gettingstarted.html
2. GWT http://code.google.com/webtoolkit/doc/latest/tutorial/RPC.html
3. AppEngine http://code.google.com/appengine/docs/java/gettingstarted/
4. AppEngine-JPA http://code.google.com/appengine/docs/java/datastore/jpa/overview.html
5. TableLess Layout for GWT HTML - http://www.w3schools.com/html/html_layout.asp

I. Defining the BLOB object for the file hosting service.
@Entity
public class FileBlob implements Serializable {
private static final long serialVersionUID = -5835124824181798205L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Blob content;
private String filename;
private String contentType;

II. Creating The Front End
  Create simple class that extends a vertical panel then add a button to display the pop-up upload dialog.

public void onClick(ClickEvent event) {
if (event.getSource() == btnUpload) {
DialogBox innerDialogBox = new BlobFileUpload(this);
// innerDialogBox.center();
innerDialogBox.show();
}
}


Create the CellTable to display the file details. http://code.google.com/webtoolkit/doc/latest/DevGuideUiCellTable.html

To enable pagination for the celltable, see GWT SimplePager.

III. Creating the BlobFileUpload dialogbox

public class BlobFileUpload extends DialogBox {
public BlobFileUpload(DownloadPanel downloadPanel) {
super();
this.downloadPanel = downloadPanel;
clear();
setText("Upload File");
//Set the servlet that will handle multi-part requests.
formPanel.setAction("/downloads/fileupload");
formPanel.setEncoding(FormPanel.ENCODING_MULTIPART);
//Set method post
formPanel.setMethod(FormPanel.METHOD_POST);
//Initialize the file upload object
fileUpload = new FileUpload();
fileUpload.setName("upload");
//Add click handler to the button, perform simple validation then call formPanel.submit
btnSubmit.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
lblLoading.setText("Uploading Please Wait");
if(!fileUpload.getFilename().trim().equals("")) {
formPanel.submit();
} else {
Window.alert("No file selected.");
}
}
});
btnClose.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
BlobFileUpload.this.hide();
}
});
verticalPanel.add(fileUpload);
verticalPanel.add(lblLoading);
controlPanel.add(btnSubmit);
controlPanel.add(btnClose);
verticalPanel.add(controlPanel);
//I don't know what this does but I saw this on some tutorial before.
formPanel.addSubmitHandler(new FormPanel.SubmitHandler() {
public void onSubmit(SubmitEvent event) {
}
});
//Callback handler when uploading is completed.
formPanel.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
String msg = event.getResults().replace("
", "").replace(
"
", "");
Window.alert("Message : " + msg);
lblLoading.setText("");
BlobFileUpload.this.downloadPanel.initData();
BlobFileUpload.this.hide();
}
});
formPanel.setWidget(verticalPanel);
add(formPanel);
}

}



IV. Creating the FileUploadServlet

Use the sample code for Apache FileUpload.
I just retrieved the filename, contact type and the content.
Then used these values to set the FileBlob object.

 public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
printf("doPost");
if (!isMultipart) {
printf("!isMultipart");
} else {
ServletFileUpload upload = new ServletFileUpload();
upload.setSizeMax(10*1024*1024);
try {
FileItemIterator iterator = upload.getItemIterator(request);
while (iterator.hasNext()) {
printf("(iterator.hasNext())");
FileItemStream item = iterator.next();
InputStream in = item.openStream();
if (item.isFormField()) {
System.out.println("if (item.isFormField())");
System.out.println("FieldName=" + item.getFieldName());
System.out.println("Name=" + item.getName());

} else {
System.out.println("} else {");
System.out.println("FieldName=" + item.getFieldName());
System.out.println("Name=" + item.getName());
System.out.println("contentType=" + item.getContentType());
try {
byte[] byteData = IOUtils.toByteArray(in);
FileBlob fileBlob = new FileBlob(item.getName(), item.getContentType(), byteData);
fileBlobDao.create(fileBlob);
printf(item.getName() + " uploaded successful");
out.println(item.getName() + " uploaded successful");
} catch (Exception ex) {
ex.printStackTrace();
out.println("ERROR " + ex.getMessage());
} finally {
IOUtils.closeQuietly(in);
}
}
}
} catch (Exception e) {
//out.println("ERROR " + e.getMessage());
//e.printStackTrace();
out.println("Upload Failed.. The size of the file is greater than 10MB");
printf("Upload Failed.. The size of the file is greater than 10MB");
}
}
}



V. creating the FileBlob Data Access Object

Creating a BLOB as with all object is straightforward in AppEngine-JPA.

public String create(FileBlob fileBlob) {
String message = null;
EntityManager entityManager = null;
try {
System.out.println("Creating : " + fileBlob.getFilename());
entityManager = EMF.get().createEntityManager();
entityManager.persist(fileBlob);
message = fileBlob.getId() + " succesfully created.";
} catch (Exception ex) {
ex.printStackTrace();
message = "Error : " + ex.getMessage();
} finally {
if (entityManager != null) {
entityManager.close();
}
}
return message;
}



VI. Retrieving Files using FileDetail.

Since we do not need all fields to be displayed on the screen, a FileDetail object which holds only what is neccessary.
@Override
public ArrayList retreiveAll() {
ArrayList fileBlobs = fileBlobDao.retrieveAll();
ArrayList listFileDetail = new ArrayList();
for(FileBlob fb : fileBlobs) {
FileDetail fd = new FileDetail();
fd.setId(fb.getId());
fd.setFilename(fb.getFilename());
listFileDetail.add(fd);
}
return listFileDetail;
}


VII. Creating the DownloadServlet

Convert the BLOB to bytes

public class FileDownloadServlet extends HttpServlet {

private static final long serialVersionUID = -2004901543318306888L;

private FileBlobDao fileBlobDao = new FileBlobDao();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String id = request.getParameter("id");
Long lId = new Long(id);
FileBlob fileBlob = fileBlobDao.findById(lId);
if(fileBlob != null) {
String contentType = fileBlob.getContentType();
if(contentType != null && !contentType.trim().equals("")) {
response.setContentType(contentType);
} else {
response.setContentType("application/octet-stream");
}
response.setHeader( "Content-Disposition", "attachment; filename=\"" + fileBlob.getFilename() + "\"" );
System.out.println("FileBlob:"+fileBlob.getContent().getBytes().length);
response.setContentLength((int)fileBlob.getContent().getBytes().length);
response.getOutputStream().write(fileBlob.getContent().getBytes());
response.getOutputStream().flush();
}
response.getOutputStream().flush();
}
}


VIII. Configurations

Don't forget to configure web.xml, persistence.xml.

IX. See the application in action downloads.androidph.com

Find file-hosting-v1.zip or click here to download this tutorial's source-code.


2 comments:

Anonymous said...

thank you very much for this tutorial sir..it's a life saver.. :)

Anonymous said...

What's Happening i'm new to this, I stumbled upon this I have discovered It absolutely helpful and it
has aided me out loads. I am hoping to give a contribution & help different customers like its helped me.

Great job.

My blog post garcinia cambogia

Email

java.padawan@androidph.com