i've got the follow issue: I wanna implement a file-reader in my GWT-application which allows the user to upload a file and work with it's content (in this particular case I'm talking about HTML). How do I realize that? As far as I know there is no way to use Java's usual BufferedReader.
The only thing I've discovered so far is the following:
try {
Request r = new RequestBuilder(RequestBuilder.GET, file).sendRequest("", new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
String text = response.getText();
System.out.println("1234");
}
#Override
public void onError(Request request, Throwable exception) {
System.out.println("456");
}
});
} catch (RequestException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But this wouldn't be that helpful as far as there's no file-chooser dialog.
I'd realy appreciate your help!
Regards
There is no ready to use FileReader API in GWT. You can build your own on top of JS Api http://www.html5rocks.com/en/tutorials/file/dndfiles/ for Firefox/Chrome and you'll have to use some kind of plugin for IE (flash for example) in order to make it work everywhere
You could upload the file to the server using the FileUpload, then immediately download the file from the server to the client, using RequestBuilder or GWT RPC, where you can then work with it. You wouldn't be able to use InputStreams or Readers as these are not actually emulated by GWT (not strictly true, see below).
If it's HTML you need to be careful - there are all sorts of security implications in allowing user generated HTML onto a page. The GWT SafeHTML mechanism can be used to address some of these issues but it is still up to you to manage this.
As an aside it is trivial to create an implementation of streams/readers that does work in GWT - the java.io.InputStream pretty much works in GWT as is but I am not sure if you can just copy this class for licensing reasons. The Apache Harmony project includes implementations that you may be able to "copy" without these restrictions.
Here is another way to read a file on the client side using the File Reader using the GWT Elemental API.
https://gist.github.com/branflake2267/180b69b9a29987214643f62fb279151f
You can't implement client-side file reader, just because of limitations of JavaScript. Client-side GWT code is compiled to JavaScript code and then JavaScript is executed within the browser. It has no access to local files or whatever.
Check this for file uploading: http://gwt.google.com/samples/Showcase/Showcase.html#!CwFileUpload
Did you have a look at this: https://developers.google.com/appengine/kb/java?hl=en#readfile ?
Related
The question can seem simple, but I didn't find a good answer yet. I need to send a JSon structure (build with an unspecified libretry I'm currently developing) from a Servlet to a remote page.
I'm interested in the best way to send the structure.
I mean, in my Servlet, inside the doPost() event, how should I manage the send?
I was thinking about 2 scenarios:
try (PrintWriter out = response.getWriter()) {
out.print(myJSon.toString(); // <- recursive function that overrides
// toString() and returns the entire JSon
// structure
} (...)
or
try (OutputStream os = response.getOutputStream()) {
myJSon.write(os, StandardCharsets.UTF8); // <- function that
// recursively writes chunk of my JSon structure
// in a BufferWriter created inside the root write function
// forcing UTF-8 encoding
} (...)
Or something different, if there's a better approch.
Note that the JSon structure contains an array of objects with long text fields (descriptions with more than 1000 characterd), so it can be quite memory consuming.
For why I'm not using standard JSon libreries, it's because I don't know them and I don't know if I can trust them yet. And also I don't know if I will be able to install them on the production server.
Thanks for your answers.
From your question i see multiple points to adress:
How to send your JSon
What JSon library can you use
How to use the library in production
How to send your JSon
From your code this seems to be an HTTP response rather than a POST on your Servlet so you need to know how to send a JSON string as an HTTP response's body
Do you use a framework for your web server or are you handling everything manually ? If you use a framework it usually does it for you, just pass the JSON String
If your doing it manually:
try (PrintWriter pw = response.getWriter()) {
pw.write(myJson.toString());
}
or
try (OutputStream os = response.getOutputStream()) {
os.write(myJson.toString().getBytes());
}
Both are valid, see Writer or OutputStream?
Your JSON's size shouldn't matter given what your saying, it's just text so it won't be big enough to matter.
What libraries can you use
There are a lot of JSON libraries for Java, mainly:
Jackson
GSon
json-io
Genson
Go for the one you prefer, there will be extensive documentation and resources all over google
How to use in production
If you are not sure you are able to install dependencies on the production server, you can always create an uber-jar (See #Premraj' answer)
Basically, you bundle the dependency in your Jar
Using Gson is good way to send json
Gson gson = new Gson();
String jsonData = gson.toJson(student);
PrintWriter out = response.getWriter();
try {
out.println(jsonData);
} finally {
out.close();
}
for detail json response from servlet in java
I want to open a link from Java I tried this
public static void main(String[] args) {
try {
//Set your page url in this string. For eg, I m using URL for Google Search engine
String url = "http://myurl.com?id=xx";
java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
}
catch (java.io.IOException e) {
System.out.println(e.getMessage());
}
}
It is working fine but the problem is that the query string is in that url. I don't want to pass it as a query string because it is a secret key. It should be passed as hidden to webpage request. How can I do this?
You can't, directly
You'd need to use a POST instead of a GET to hide the value and the URL does not encode the method used to access it, so it will always use GET.
You could conceivably write out a HTML file that automagically does a POST to the desired URL (using some JavaScript) and open that (using a file:// URL).
But note that "hiding" the parameter like this adds no real security! An interested user that wants to know the value that his PC sends to some site will be able to see it. It might take slightly more effort to find it, but it's definitely not impossible.
If there is no need to show the particular url in a browser, then you could handle the link as an HttpURLConnection (see JavaDoc).
And here you have an example.
I need to read several megabytes (raw text strings) out of my GAE Datastore and then write them all to a new PDF file, and then make the PDF file available for the user to download.
I am well aware of the sandbox restrictions that prevent you from writing to the file system. I am wondering if there is a crafty way of creating a PDF in-memory (or a combo of memory and the blobstore) and then storing it somehow so that the client-side (browser) can actually pull it down as a file and save it locally.
This is probably a huge stretch, but my only other option is to farm this task out to a non-GAE server, which I would like to avoid at all cost, even if it takes a lot of extra development on my end. Thanks in advance.
You can definitely achieve your use case using GAE itself. Here are the steps that you should follow at a high level:
Download the excellent iText library, which is a Java library to work with PDFs. First build out your Java code to generate the PDF content. Check out various examples at : http://itextpdf.com/book/toc.php
Since you cannot write to a file directly, you need to generate your PDF content in bytes and then write a Servlet which will act as a Download Servlet. The Servlet will use the Response object to open a stream, manipulate the Mime Headers (filename, filetype) and write the PDF contents to the stream. A browser will automatically present a download option when you do that.
Your Download Servlet will have high level code that looks like this:
public class DownloadPDF extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
//Extract some request parameters, fetch your data and generate your document
String fileName = "<SomeFileName>.pdf";
res.setContentType("application/pdf");
res.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
writePDF(<SomeObjectData>, res.getOutputStream());
}
}
}
Remember the writePDF method above is your own method, where you use iText libraries Document and other classes to generate the data and write it ot the outputstream that you have passed in the second parameter.
While I'm not aware of the PDF generation on Google App Engine and especially in Java, but once you have it you can definitely store it and later serve it.
I suppose the generation of the PDF will take more than 30 seconds so you will have to consider using Task Queue Java API for this process.
After you have the file in memory you can simply write it to the Blobstore and later serve it as a regular blob. In the overview you will find a fully functional example on how to upload, write and serve your binary data (blobs) on Google App Engine.
I found a couple of solutions by googling. Please note that I have not actually tried these libraries, but hopefully they will be of help.
PDFJet (commercial)
Write a Google Drive document and export to PDF
I have a simple JSR 286 Portlet that displays a user manual (pure HTML code, not JSP).
Actually, my doView method, just contains this :
public class UserManualPortlet extends GenericPortlet
{
#Override
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(
"/html/usermanual.html");
rd.include(request, response);
}
}
This works as expected, however I'm having trouble when including images. I'm aware that the path to images should be something like :
<img src='<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/html/image.jpg")%>'/>
However, my HTML file containing the user manual is used elsewhere, so I would like to preserve it as a pure HTML file.
Is there a way to dynamically replace my classic images urls by something like the example above ? Perhaps using the PrintWriter of the response ?
If such thing is not possible, I thing I would need to generate a JSP file during my Maven build.
Any solution or ideas are welcome.
With JSR-268 portlets you have a better way of referencing resources: create ResourceURL using renderResponse.createResourceURL() and then you set the resourceID in the ResourceURL. That should give more consistent results across all portlet containers.
That said, if you want to modify the generated content from your usermanual.html but you don't want to convert it to a JSP then, instead of using a request dispatcher, I would load the file contents on my own, parse it at the same time that I do the URL replacements and then print all the contents to the portlet's response.
I've been using Liferay a lot for past 2 years, but I have never needed any extensive document management.
Now I have a portlet where users upload documents (MS office OLE2 documents, ODS documents, PDF etc.) and I have to persist them with all metadata available.
I know how would I do that without using Liferay, I'd probably use Apache solr with Apache Tika (UpdateRichDocuments and ExtractingRequestHandler) or Apache Jackrabbit that are using Apache Tika under the hood (org.apache.jackrabbit.extractor.*).
The problem is, that If I look at the trunk of Liferay, there are some key classes :
Hooks (JCRHook, FileSystemHook, CMISHook, s3Hook) that are employed from within DLLocalServiceImpl kinda directly
Another alternative is using DLAppLocalServiceImpl that is employing DLRepositoryLocalServiceImpl and the files are persisted into repository also via Hooks, but a lot of additional stuff is done in there.
There is not jackrabbit-text-extractors library in Liferay, so I suppose If I wanted metadata to be extracted from PDF, DOCs, ODS documents, I would have very hard times... because the DL service layer doesn't accept additional properties
I think I'd have to avoid using DL services and JCR hook and access Jackrabbit directly... But I would loose the compatibility and possibility migrate my repository etc.
Could please anybody collaborate on this one please ? Thank you
SOLR for indexing, Jackrabbit for document storage. Managing Liferay Document Library in code is fairly easy, just look at the DL*LocalServiceUtil classes, namely DLFolderLocalServiceUtil and DLFileLocalServiceUtil. By default Liferay just creates a matching folder/file structure on the hard drive (with names changed) so you'd only need to write code or use Jackrabbit if you wanted more than this since Liferay allows up/download and viewing out of the box via the control panel and various portlets.
I haven't used JackRabbit with Liferay but once configured everything should be managed under the covers and you shouldn't need to worry about it on the front end.
When you say "with all metadata available" I'm not sure what is retained, but aside from renaming the file so that it can be tracked there shouldn't be any other changes. It should be quick and easy to test by uploading a file of each type and checking the entries in the LIFERAY/data/document_library directory and subdirectories. Again this would be different if Jackrabbit is used.
those two services DLLocalServiceImpl and DLAppLocalServiceImpl both are and will, I suppose, important. The former one if for direct access to repository. Notice that when adding a file via this service you need to persist corresponding DlFileEntry into database and than reference that addFile(...., fileEntryId, ...).
The latter service is doing additional stuff for you, mainly asset management and workflow.
Regarding your use case, I would avoid using document library, because no metadata can go down into the JCR repository. Actually only metadata/custom properties that you could store would be custom properties AKA Expando feature of Liferay portal.
Best way for you seem to be implement your own jackrabbit hook to store data into repository and let Liferay document library use that repository.
Think Edgar is correct. If you check the current trunk via http://svn.liferay.com/repos/public/portal/trunk/portal-service/src/com/liferay/documentlibrary/service/DLLocalService.java (login as guest and no password), you will no longer find the class DLFolderLocalServiceUtil. We are using the existing DLFolderLocalServiceUtil class as well. Thanks for the heads up. We will refactor our code so when 6.1 comes around we can still use the DocumentLibrary services.
You need to always use DLAppServiceUtil ( as Liferay instructs specifically ). Here is my working code that saves a file to the CMS:
public static void saveFileToCMS(ActionRequest aReq, long groupId, String fileName, File filenameWithPath) {
try {
ServiceContext serviceContext = ServiceContextFactory.getInstance(
Group.class.getName(), aReq);
// prevents duplicate entries based on unique title name
Random rand = new Random();
Integer suffix = new Integer(rand.nextInt(10000));
DLAppServiceUtil.addFileEntry(groupId, 0, fileName, "application/vnd.ms-excel",
fileName + suffix.toString(), "description goes here", "changelogname",
filenameWithPath, serviceContext);
//log.info("Successfully added the new file");
} catch (PortalException pe) {
log.error("Portal Exception occurred while saving file to CMS");
pe.printStackTrace();
} catch (SystemException e) {
log.error("System Exception occurred while saving file to CMS");
e.printStackTrace();
}
}