I'm trying to figure out how to upload one file using GWTs FileUpload widget. I'm using GWT and Google AppEngine with Java but I would like to upload file to my own Linux server.
I have the following code already but now I can't figure out how to submit my file to the Google AppServer server and save it to another server:
public class FileUploader{
private ControlPanel cp;
private FormPanel form = new FormPanel();
private FileUpload fu = new FileUpload();
public FileUploader(ControlPanel cp) {
this.cp = cp;
this.cp.setPrimaryArea(getFileUploaderWidget());
}
#SuppressWarnings("deprecation")
public Widget getFileUploaderWidget() {
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);
// form.setAction(/* WHAT SHOULD I PUT HERE */);
VerticalPanel holder = new VerticalPanel();
fu.setName("upload");
holder.add(fu);
holder.add(new Button("Submit", new ClickHandler() {
public void onClick(ClickEvent event) {
GWT.log("You selected: " + fu.getFilename(), null);
form.submit();
}
}));
form.addSubmitHandler(new FormPanel.SubmitHandler() {
public void onSubmit(SubmitEvent event) {
if (!"".equalsIgnoreCase(fu.getFilename())) {
GWT.log("UPLOADING FILE????", null);
// NOW WHAT????
}
else{
event.cancel(); // cancel the event
}
}
});
form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
Window.alert(event.getResults());
}
});
form.add(holder);
return form;
}
}
Now, what do I need to do next? What do i need to put in web.xml and how do I write my servlet so i can store file and return url of that object (if possible)
Here's the code from my app:
1) I created a class to accept http request:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class FileUpload extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletFileUpload upload = new ServletFileUpload();
try{
FileItemIterator iter = upload.getItemIterator(request);
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
// Process the input stream
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len;
byte[] buffer = new byte[8192];
while ((len = stream.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, len);
}
int maxFileSize = 10*(1024*1024); //10 megs max
if (out.size() > maxFileSize) {
throw new RuntimeException("File is > than " + maxFileSize);
}
}
}
catch(Exception e){
throw new RuntimeException(e);
}
}
}
2) Then in my web.xml I've added these lines:
<servlet>
<servlet-name>fileUploaderServlet</servlet-name>
<servlet-class>com.testapp.server.FileUpload</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>fileUploaderServlet</servlet-name>
<url-pattern>/testapp/fileupload</url-pattern>
</servlet-mapping>
3) And for form.action did this:
form.setAction(GWT.getModuleBaseURL()+"fileupload");
I would suggest using GWTUpload because it's dead simple to use and extend. You can add it to your project in less than 10 minutes and it supports GAE right out of the box (using GWTUpload-GAE). See the examples for some common usage scenarios.
In GWT, you can post the file to the server using http form methods, and you must use the supplied HttpServlet to accept and save the data as binary blogs in the Appengine BigTable.
Then, you need a second HttpServlet to read the file from bigtable, SET THE MIME TYPE IN THE HTTP HEADER {and caching options}, and then stream the file to the user.
Although RPC isn't NECESSARILY needed, you must let the client know what the generated fileId is so they can access it {unless you want to let user's supply the id and force them to worry about name overrides... ...ick}. Either you can use rpc to ask for a list of / single id {like "newest file id by user"}, or you can return that id in the body of the UploadServlet's response... but then you must make sure your post target is an in-page iframe, poll to make sure the iframe has a body between the submit event and the actual server response, and then parse and use that id in gwt to create an img or object tag that uses the file.
The key part is having one servlet for upload, and another to download. Remember, BigTable just stores binary blobs, so you also need your data entity to have a mime/content Type that can be read from the input file {never rely on file extensions!}. Also, there's a 1MB per entity in the BigTable, and a 10MB request limit for free accounts. You may wish to have your data entity contain a list of 1-10 blobs, each of which are a max 1024bytes.
Basically, your best bet is to find a working, free copy, like Google File Service, and extend it to learn how the system works.
If you wish, I will be posting my own open-source version of file handling, once I finish the gwt control widgets and can consider it all stable enough to be useful to anyone. Email x AT aiyx DOT info if you want me to send you a jar of betalicious code.
Here you go with a complete GWT fileupload with Progress bar
Here you can DOWNLOAD the source
Related
I am new in GWT and I am working on a project where GWT is used to generate a form. In this form I have added a table in a Vertical panel. Now I want to export this table in excel or CSV. Wondering if someone can help me on this issue.
This is sample code of the entry point class:
public class ItemListEditor implements EntryPoint
{
private final Button addRow = new Button("Add Row");
private final Button save = new Button("Save");
private final Button next = new Button("Next");
private final Button upload = new Button("Upload");
private final Button export = new Button("Export");
private ItemTable table = null;
}
Again, my problem is only to export this table- like when click on export button, system will ask for the location.
I can provide more information if needed.
Please help on this issue
Create a HTTPServlet class, inside the doGet() method of the servlet create a HSSFWorbook using the Apache Poi jar, write your data in the sheet, write the workbook in the response part of servlet.
Map the servlet in your web.xml file and finally, use this servlet url inside your button handler..
EDITED ----->
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent arg0) {
exlGenerationServiceAsync.excelReportObjects(new AsyncCallback() {
#Override
public void onFailure(Throwable arg0) {
arg0.printStackTrace();
}
#Override
public void onSuccess(Object arg0) {
Window.open(GWT.getModuleBaseURL() + "url", "", "");
}
});
}
}
Servlet mapping inside the web.xml file----->
<servlet>
<servlet-name>excelFile</servlet-name>
<servlet-class>com.company.server.excelFileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>excelFile</servlet-name>
<url-pattern>/yourUrl</url-pattern>
</servlet-mapping>
Where excelFileServlet is my servlet class.
Inside Servlet class---->
File file = new File("Path Where you want to write your excel file");
response.setContentType("application/vnd.ms-excel");
response.addHeader("Content-Disposition", "attachment; filename=" + "Excel_Report_Name.xls");
response.setContentLength((int) file.length());
FileInputStream fileInputStream = new FileInputStream(file);
try{
OutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
responseOutputStream.close();
}catch(Exception e){
e.printStackTrace();
System.err.println("Inside Try/catch");
If you're looking for some quick and raw exportation, you can give a try to https://code.google.com/p/gwt-table-to-excel/. The project is not very active.
Otherwise, if you want to have more control on the formatting and data you have to send the content of the table to the server side using RPC or other, and then you can use Apache POI to export it as you do usually in Java.
I have just installed GWT 2.6 and am now getting the error "Description Resource Path Location Type
The file war\WEB-INF\lib\gwt-servlet.jar has a different size than GWT SDK library gwt-servlet.jar; perhaps it is a different version? gwt-servlet.jar /AwardTracker/war/WEB-INF/lib Unknown Google Web Toolkit Problem"
I downloaded the GWT 2.6 zip and then copied the directory "GWT-2.6.0" into "Eclipse\eclipse-jee-juno-SR1-win32\eclipse\plugins". I then right clicked on the project and selected "properties/Google/Web Toolkit/Configure SDKs.../Add". I then browsed to the "GWT-2.6.0" directory, added it and selected it.
I followed the solution from Braj and received the following errors when I recompiled:
Compiling module org.AwardTracker.AwardTracker
Validating units:
Ignored 2 units with compilation errors in first pass.
Compile with -strict or with -logLevel set to TRACE or DEBUG to see all errors.
Computing all possible rebind results for 'gwtupload.client.DecoratedFileUpload.DecoratedFileUploadImpl'
Rebinding gwtupload.client.DecoratedFileUpload.DecoratedFileUploadImpl
Could not find an exact match rule. Using 'closest' rule based on fall back values. You may need to implement a specific binding in case the fall back behavior does not replace the missing binding
[ERROR] Errors in 'gwtupload/client/DecoratedFileUpload.java'
[ERROR] Line 347: Rebind result 'gwtupload.client.DecoratedFileUpload.DecoratedFileUploadImpl' cannot be abstract
The above was fixed by downloading gwtupload-1.0.1.jar, using 'Add External JARS' to add it to the library and removing the old gwtupload-0.6.6.jar. I then recompiled and the compile work. However, now I have an error in my "MyCustomisedUploadServlet" on the line (this error was not present before):
protected static final String XML_ERROR_ITEM_NOT_FOUND = "<" + TAG_ERROR + ">item not found</" + TAG_ERROR + ">";
The rest of the code is:
package org.AwardTracker.server;
import gwtupload.server.UploadAction;
import gwtupload.server.exceptions.UploadActionException;
import gwtupload.shared.UConsts;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
/**
* This is an example of how to use UploadAction class.
*
* This servlet saves all received files in a temporary folder,
* and deletes them when the user sends a remove request.
*
* #author Manolo Carrasco Moñino
*
*/
public class MyCustomisedUploadServlet extends UploadAction {
private static final long serialVersionUID = 1L;
protected static final String XML_ERROR_ITEM_NOT_FOUND = "<" + TAG_ERROR + ">item not found</" + TAG_ERROR + ">";
Hashtable<String, String> receivedContentTypes = new Hashtable<String, String>();
/**
* Maintain a list with received files and their content types.
*/
Hashtable<String, File> receivedFiles = new Hashtable<String, File>();
/**
* Override executeAction to save the received files in a custom place
* and delete this items from session.
*/
#Override
public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
String response = "";
#SuppressWarnings("unused")
int cont = 0;
for (FileItem item : sessionFiles) {
if (false == item.isFormField()) {
cont ++;
try {
/// Create a temporary file placed in the default system temp folder
File file = File.createTempFile("upload-", ".bin");
item.write(file);
/// Save a list with the received files
receivedFiles.put(item.getFieldName(), file);
receivedContentTypes.put(item.getFieldName(), item.getContentType());
/// Send a customised message to the client.
response += file.getAbsolutePath();
} catch (Exception e) {
throw new UploadActionException(e);
}
}
}
/// Remove files from session because we have a copy of them
removeSessionFileItems(request);
/// Send your customised message to the client.
return response;
}
/**
* Get the content of an uploaded file.
*/
#Override
public void getUploadedFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
String fieldName = request.getParameter(UConsts.PARAM_SHOW);
File f = receivedFiles.get(fieldName);
if (f != null) {
response.setContentType(receivedContentTypes.get(fieldName));
FileInputStream is = new FileInputStream(f);
copyFromInputStreamToOutputStream(is, response.getOutputStream());
} else {
renderXmlResponse(request, response, XML_ERROR_ITEM_NOT_FOUND);
}
}
/**
* Remove a file when the user sends a delete request.
*/
#Override
public void removeItem(HttpServletRequest request, String fieldName) throws UploadActionException {
File file = receivedFiles.get(fieldName);
receivedFiles.remove(fieldName);
receivedContentTypes.remove(fieldName);
if (file != null) {
file.delete();
}
}
}
I simply commented this line out (" protected static final String XML_ERROR_ITEM_NOT_FOUND = "<" + TAG_ERROR + ">item not found";"), recompiled and ran it and it works fine. I hope all this helps others. Thank you to Braj for his help.
This works for me very well
Select the warning, right click and choose
"Quick fix" -> "Synchronize /WEB-INF/lib with SDK libraries"
"Done"
Whenever you change the GWT version you have to clean your project from the stub that is auto-generated by the previous GWT version as shown in below screenshots.
Problem: The file war\WEB-INF\lib\gwt-servlet.jar has a different size than GWT SDK library gwt-servlet.jar; perhaps it is a different version?
Solution: The problem in your case is gwt-servlet.jar that is auto-generated by previous GWT version. Just delete it along with other stub and re-compile project again.
To copy the sdk in the plugin directory is not the corret way to add another SDK version.
Use Preferences -> Google -> Web Toolkit to add another GWT SDK version.
In your project choose:
project properties -> Goolge -> Web Toolkit you can choose the SDK the project should use.
I changed my compiler from 1.8 to 1.7 and lost this message.
Ï am Taking data From server written in "C" using Sockets .
My java class name is ReceivingData, and here's the code for receiving the data and storing it in ArrayList and passing the ArrayList to other Class's Constructor.
package pack.exp;
import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ReceivingData implements Runnable
{
public static void main(String[] args)
{
Thread t = new Thread(new ReceivingData());
t.start();
}
public List<String> obj1;
#Override
public void run()
{
Socket s;
InputStream stream;
try
{
s = new Socket("10.9.211.22", 6870);
stream = s.getInputStream();
byte[] data = new byte[13];
int read;
String can_Id= null;
while((read = stream.read(data)) != -1)
{
String can_Data=
String.format("%02X:%02X:%02X:%02X,
data[0], data[1], data[2], data[3]);
List<String> obj1= new ArrayList<String>();
obj1.add(can_Data.substring(0, 2));
obj1.add(can_Data.substring(3, 5));
obj1.add(can_Data.substring(6, 8));
obj1.add(can_Data.substring(9, 11));
Receiving_At_Regular_IntervalServlet rari= new
Receiving_At_Regular_IntervalServlet(obj1);
Thread.sleep(3000);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
This is the Servlet which is receiving the data from ArrayList passed by the above File.
and storing this data from the arraylist in to the Entity for datastore and deploys it on the Google App engine.
package pack.exp;
#SuppressWarnings("serial")
public class Receiving_At_Regular_IntervalServlet extends HttpServlet
{
List<String> obj2= new ArrayList<String>();
public Receiving_At_Regular_IntervalServlet(List<String> obj2) throws
IOException
{
this.obj2= obj2;
System.out.println("Receiving in Web Project" + obj2);
System.out.println("");
System.out.println("");
}
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws
IOException
{
Key k1 = KeyFactory.createKey("C","0D F0 0800 1");
String parameter1 = obj2.get(0);
Entity can1 = new Entity(k1);
can1.setProperty("First Parameter", parameter1);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(can1);
Entity can11 = null;
try
{
can11= datastore.get(k1);
}
catch (EntityNotFoundException e)
{
e.printStackTrace();
}
String first_P= (String) can11.getProperty("First Parameter");
resp.setContentType("text/plain");
resp.getWriter().println("Parameter--- " + first_P);
}
}
The ReceivingData code evidently runs a thread and reads data from 10.9.211.22 port 6870 using Socket from a local computer. That's fine. It converts four bytes to a List and passes that to Receiving_At_Regular_IntervalServlet. Fine but not what you need.
This part might work on a development computer but won't work if deployed to the cloud. AppEngine servers does not permit developers to define main(), use Socket or communicate with private IP subnet 10. Forget about deploying that code to AppEngine.
Receiving_At_Regular_IntervalServlet has a custom constructor. AppEngine does not call your constructor because its servlet code expects only the default constructor. That is probably when your 503 error occurs.
With servlets the data is not supposed to come in via a constructor. Data must come in via members of the request parameter of the doGet method (though to be RESTful you should rather use doPut in this example). You insert the data into the request parameter but sending a correctly constructed http request to the server. Your code lacks that web application design.
Build your main program and your AppEngine code in separate projects and make main talk to servlet using http.
HTTP ERROR 503 error
You can't help anything when a server throws this error. It is only thrown when a service from the server is unavailable.
You need explicit handling on such error codes, other than 200 OK, in the client app and appropriate message has to be shown or as the alternate requirement suggestion.
Refer to:
Status Code definitions
Java - 503 - SC_SERVICE_UNAVAILABLE
I have a java web application based on Spring MVC.
The task is to generate a pdf file. As all knows the spring engine has its own built-in iText library so the generating of pdf file is really simple. First of all we need to do is to overload AbstractView and create some PdfView. And the seconf thing is to use that view in controller. But in my application I am also have to be able to store generated pdf files on local drive or give my users some link to download that file. So the view in that case is not suitable for me.
I want to create some universal pdf generator that creates a pdf file and returns the bytes array. So I can use that array for file storing (on hard drive) or printing it directly in browser. And the question is - are there any way to use such engine (that returns only the bytes array) in PdfVIew solution? I am asking because overloaded buildPdfDocument method (in PdfView) already have PdfWriter and Document parameters.
Thank you
tldr; you should be able to use a view and save it to a file.
Try using Flying Saucer and its iTextRenderer when you overload AbstractPdfView.
import org.xhtmlrenderer.pdf.ITextRenderer;
public class MyAbstractView extends AbstractView {
OutputStream os;
public void buildPdfDocument(Map<String,Object> model, com.lowagie.text.Document document, com.lowagie.text.pdf.PdfWriter writer, HttpServletRequest request, HttpServletResponse response){
//process model params
os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
String url = "http://www.mysite.com"; //set your sample url namespace here
renderer.setDocument(document, url); //use the passed in document
renderer.layout();
renderer.createPDF(os);
os.close();
}
}
protected final void renderMergedOutputModel(Map<String,Object> model,
HttpServletRequest request,
HttpServletResponse response)
throws Exception{
if(os != null){
response.outputStream = os;
}
public byte[] getPDFAsBytes(){
if(os != null){
byte[] stuff;
os.write(stuff);
return stuff;
}
}
}
You'll probably have to tweak the sample implementation shown here, but that should provide a basic gist.
I use Apache Commons FileUpload in a java server-side app that has a html form with fields :
A destination fied that will be filled with email address of the destination mailbox
A message text with a message of the sender
A < input type=file ... field for uploading a photo. I can receive uploaded file (as a stream) but how
This app I want to upload on GAE .
I can receive uploaded file (as a stream , using org.apache.commons.fileupload.FileItemStream).
I want to receive too input textfields (i.e. 1) and 2)) - completed by the user of app)
I want to access these using org.apache.commons.fileupload.FileItem but I receive java.rmi.server.UID is a restricted class
You should use the FileItemIterator of the Apache Commons FileUpload.
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.io.InputStream;
..
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
ServletFileUpload upload = new ServletFileUpload();
res.setContentType("text/plain");
FileItemIterator iterator = upload.getItemIterator(req);
while (iterator.hasNext()) {
FileItemStream item = iterator.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (item.isFormField()) {
//regular form field
resp.getWriter().println(("Form:" + name + " : " + Streams.asString(stream));
} else {
//fileform field
resp.getWriter().println(("File:" +name + " : " + item.getName());
}
}
} catch (Exception ex) {
throw new ServletException(ex);
}
}
Take a look at this: Google App Engine and FileUpload
You can't write directly to the filesystem in GAE, but take a look at GAEVFS, which uses the datastore and memcache to emulate a filesystem.