How can I receive the file contents in my Vaadin service? - java

I want to add an upload button to my web application. In the HTML template, I added:
<link rel="import" href="../../../bower_components/vaadin-upload/src/vaadin-upload.html">
<h2 id="header-Upload">Upload</h2>
<vaadin-upload nodrop/>
I now want to receive the stream in my backend Vaadin process. This stream can be then inserted in the database.
The documentation on https://vaadin.com/components/vaadin-upload/html-examples/upload-basic-demos doesn't provide this information.
I believe I should somehow link a StreamReceiver to the <vaadin-upload> in question, but I am not sure how to do that.
I am using Vaadin Flow (version 12).
Additional information
I tried the following:
In HTML:
<vaadin-upload id="upload" nodrop/>
In Java:
public class MyView extends PolymerTemplate<Model> {
private final MemoryBuffer buffer = new MemoryBuffer();
#Id("upload")
private final Upload upload = new Upload(buffer);
public MyView() {
upload.addSucceededListener(event -> {
System.out.println(event.getFileName());
System.out.println(buffer.getInputStream());
});
}
}
When I upload a file, I get the following exception:
[qtp162821120-20] ERROR com.vaadin.flow.server.DefaultErrorHandler -
com.vaadin.flow.server.UploadException: Upload failed
at com.vaadin.flow.server.communication.StreamReceiverHandler.streamToReceiver(StreamReceiverHandler.java:429)
Caused by: java.lang.IllegalStateException: Upload cannot be performed without a receiver set
at com.vaadin.flow.component.upload.Upload$DefaultStreamVariable.getOutputStream(Upload.java:581)
at com.vaadin.flow.server.communication.StreamReceiverHandler.streamToReceiver(StreamReceiverHandler.java:358)

massive Edit: The actual solution to your problem was that you instantiated the Upload in your java class, when you should let Vaadin do this (because of the polymer template) and refer to this upload component using an identifier both in the html template (<vaadin-upload id="upload" nodrop/>) as well as in the java code (#Id("upload") private Upload upload;). You can now set the receiver of the upload in the java class using upload.setReceiver(buffer);.
public class MyView implements PolymerTemplate<Model> {
#Id("upload") // com.vaadin.flow.component.polymertemplate
private Upload upload; // NO INSTANTIATION!
private private final MemoryBuffer buffer = new MemoryBuffer();
public MyView (){
upload.setReceiver(buffer);
upload.addSucceededListener(event -> {
System.out.println(event.getFileName());
System.out.println(buffer.getInputStream());
});
}
}
My initial answer was using an unnecessary alternative approach that was not related to your problem (I thought so at first), but helped finding the real solution.

The best solution depends a bit about your context, mainly how does your backend accept the data? Does it accept inputstream where it can read the data, does it provide you an outputstream where to write it or is there a simple byte[] where to buffer the content.
If you are using Binder in your form, you could use ByteArrayUploadField from Viritin add-on, which directly binds to byte[] type that you probably have in your domain object.
I recently wrote an article that explains the functionality of Vaadin Upload component. Check that for more details.

Related

automated testing webdrive webpage translation

I am trying to write an app using automated testing with webdriver in Java (I am really new to this), I can already log in and crawl the data I need from a website, the problem is that the page is in chinese and I am trying to display it in English in my app. I have found information about using right click but only on a WebElement, is there anyway I can right click on the page and translate to English or any other method to achieve this?
Thanks
Personally I would continue to retrieve the information in Chinese.
Store each type for example an id as a String. Then use an external library such as the Google Cloud Translate and then pass that id as the following:
public static void translateText(id, String sourceLang, String targetLang, PrintStream out)
{
Translate trans = createTranslateService();
TranslateOption srcLang = TranslateOption.sourceLanguage(sourceLang);
TranslateOption targLang = TranslateOption.sourceLanguage(targetLang);
TranslateOption model = TranslateOption.model("nmt");
Translation translation = translate.translate(id, srcLang, targLang, model);
translation.getTranslatedText());
// Then you can save this into a new variable and pass it onto your website as you need to.
}

Chunked uploading of media with Twitter4J

I am trying to upload a video on Twitter. I am using the following code:
private UploadedMedia uploadMediaChunkedInit(long size) throws TwitterException {
return new UploadedMedia(post(
conf.getUploadBaseURL() + "media/upload.json",
new HttpParameter[] { new HttpParameter("command", CHUNKED_INIT),
new HttpParameter("media_type", "video/mp4"),
new HttpParameter("total_bytes", size) }).asJSONObject());
}
Where I am getting following error:
Method post is not defined
I got this code from here:
https://github.com/yusuke/twitter4j/pull/226/commits/73b43c1ae4511d3712118f61f983bcbca4ef0c59
Those methods are private implementation details/utilities of the TwitterImpl class.
See lines 1844-1860 and lines 1862-1878
(notice they are private).
You are approaching this incorrectly. Never should you have to call an internal implementation detail. Instead, use the public API of Twitter4J. You should use the uploadMediaChunked method instead. There is currently no javadoc I can link you to (since it's a relatively new feature).
I also see that this feature is not yet released. For now, you can build Twitter4J yourself and then use its public API (instead of copying source code into your own project).

Tapestry 5 - Dynamically generate URL of file in web app context folder in Java code

I am displaying a static image asset inside a component, and I don't know until runtime what that image should be, so I need to dynamically generate the URL. These images all live in webapp/images/
The documentation I found is not very clear on how to handle this usecase, but after playing around I figured out I can construct the URL dynamically in the component template like so:
<img src="${context:img/score/overall}/${imageFilename}" />
Then put the logic for which image to display in the component class file:
public String getImageFilename() {
// decide which image to display and return the filename
}
So this works, but it's not the cleanest solution. I don't really want to concatenate the URL base to the filename inside the template - I'd much rather construct the entire URL in the component class, like so:
<img src="${imageUrl}" />
and
public String getImageURL() {
// build URL somehow like "context:" + "filePath" in template
}
So my question is: Is there a Java code equivalent of context: ... in the template that simply produces a String base URL for the web appl context folder that I can append my file path to?
I can see some obvious hacky ways of doing it from reading the docs, like manually constructing the base URL using the scheme described, or injecting a known static image as an Asset from the web app context folder and calling toClientURL() to extract the base URL. But it seems like there must be a nice built-in way to do this in Java, especially since it's freely available to use in a template expansion.
But google as I might, I can't seem to find how to do this anywhere!
I think this should do the trick for you. (disclaimer: I have not tested it)
#Inject
private AssetSource assetSource;
#Inject
private Locale locale;
public String getImageURL() {
URL assetUrl = assetSource.getContextAsset("img/score/overall/" + getImageFilename(), locale).toURL();
return assetUrl.toString();
}
Edit: Updated to reflect Howards comment

Notification when file download completes in Play framework

I'm successfully using Play 1.2.4 to serve large binary file downloads to users using the renderBinary() method.
I'd like to have a hint of when the user actually completes the download. Generally speaking, I know this is somewhat possible as I've done it before. In an old version of my website, I wrote a simple servlet that served up binary file downloads. Once that servlet finished writing out the contents of the file, a notification was sent. Certainly not perfect, but useful nonetheless. In my testing, it did provide an indication of how long the user took to download a file.
Reviewing the Play source, I see that the play.mvc.results.RenderBinary class has a handy apply() method that I could use. I wrote my own version of RenderBinary so I could send the notification after the apply() method finished writing out the file contents.
The problem I found is that calls to response.out.write() obviously cache the outgoing bytes (via Netty?), so even though I am writing out several megabytes of data, the calls to play.mvc.Http.Response.out.write() complete in seconds, even though it takes the downloader a couple minutes to download the file.
I don't mind writing custom classes, although I'd prefer to use a stock Play 1.2.4 distribution.
Any ideas on how to get a notification of when the end of a file download is pushed out towards the user's browser?
It seems this may help you, as it tackles a somehow similar problem:
Detect when browser receives file download
I'm not sure you'll eb able to do it via renderBinary nor an #After annotation in the controller. Some browser-side detection of the download and then a notification to the server (pinging the download's end) would work.
There may be an alternative: using WebSockets (streaming the file via the socket and then having teh client to answer) but it may be overkill for this :)
you can use ArchivedEventStream.
first create a serializable ArcivedEventStream class..
public class Stream<String> extends ArchivedEventStream<String> implements Serializable{
public Stream(int arg0) {
super(arg0);
}
}
then on your controller...
public static void downloadPage(){
Stream<String> userStream = Cache.get(session.getId(),Stream.class);
if( userStream == null){
userStream = new Stream<String>(5);
Cache.add(session.getId(), userStream);
}
render();
}
public static void download(){
await(10000);// to provide some latency. actually no needed
renderBinary(Play.getFile("yourfile!"));
}
public static void isDownloadFinished(){
Stream<String> userStream = Cache.get(session.getId(),Stream.class);
List<IndexedEvent<String>> list = await(userStream.nextEvents(0));
renderJSON(list.get(0).data);
}
#After(only="download")
static void after(){
Stream<String> userStream = Cache.get(session.getId(),Stream.class);
userStream.publish("ok");
}
on your html...
#{extends 'main.html' /}
#{set title:'downloadPage' /}
download
<script>
$(document).ready(function(){
$.ajax('/application/isDownloadFinished',{success:function(data){
if(data){
console.log("downloadFinished");
}
}});
});
</script>
when your download finished, the original page will retrieve the notification.
This code is just a sample. You could read the api of ArchivedEventStream and make your own implementation..

Best way to display picture attachments in playframework?

I'm using playframework-1.2.3 and i have a data model looks like this:
public class Item extends Model {
...
public Blob img;
}
The images are stored with no extensions(like "0f4fb5da-ed95-4c22-b3ec-725489285848") in my system.
I display the images this way followed the tutor:
<img src="#{items.getImg(i.id)}" height="210px"/>
But what i want is not request the controller every time i display it, is there any way allow me to display images with static file link ?
This may need two steps:
1.stored images with a extension.
2.change the file attachments dir under /public.
So , can any one help ?
Is there any real problem having it go via your controller? This actually gives you a better level of abstraction.
However, if you did want to do it statically, then you could create a new staticDir route, rather than moving your images into your public folder. For example
GET /img/ staticDir:usrImages
If you need any level of security over who can see these images though, I would caution against using a public access method like this. Using a controller allows you to do a session check, to ensure the user has appropriate access to view the image.
Edit - I would suggest reading Peter Hilton's blog on this - http://www.lunatech-research.com/playframework-file-upload-blob

Categories

Resources