How to download a PDF from Vaadin Flow App? - java

How would one go about download a pdf in Vaadin? It seems it would have something to do with the anchor button, but don't know how one would go about downloading it.
I have looked at multiple resources, but none have helped. This is a prewritten pdf, not dynamically created, so that removes a bunch of questions. This one is designed around Vaadin7, which does not help me.

If the PDF is among your public, static files, such as in src/main/resources/META-INF/resources in a Spring app, it's as simple as this, where the file path "sample.pdf" is relative to src/main/resources/META-INF/resources.
Anchor anchor = new Anchor("sample.pdf", "Download PDF");
anchor.getElement().setAttribute("download", "downloaded-file-name.pdf");
add(anchor);
Otherwise, you can use this approach. In my case, the file's location is src/main/resources/sample2.pdf.
StreamResource streamResource = new StreamResource("whatever.pdf",
() -> getClass().getResourceAsStream("/sample2.pdf"));
Anchor anchor = new Anchor(streamResource, "Download PDF");
anchor.getElement().setAttribute("download", "downloaded-other-name.pdf");
add(anchor);
Note the leading slash in /sample2.pdf, it's important.
If we don't set the download attribute, the file might be opened instead of downloaded, under the name whatever.pdf.
If we set the download attribute to an empty string, it will be downloaded under the name whatever.pdf. Otherwise, it will be downloaded under the name we provide in the attribute.

Related

Adding/Loading an image in java

I am trying to load an image to display on the screen (just to get an idea of how to do it).
The problem is that when the program tries to load "apple.png" (which is saved on my desktop), it cannot find the image - Where do image files need to be stored in order for them to be found? Here is my loading method:
private void loadImage() {
ImageIcon appleIcon = new ImageIcon("apple.png");
Image appleImage = appleIcon.getImage();
}
If you want to reach it from the desktop, you should use the complete path. The easiest way to handle resources would be to create a folder in you java project, which you can access via "folderName/fileName.example".
Using the full path is an option
C:\filefolder\file.jpg
To answer your question though
Wherever your java file is is where it's going to think "home is" make yourself a java workspace to put your java source files in and inside it create a folder to put any assets you want in that way you will simply be able to call "apple.jpg"
if you want use the file name only, the file path ("apple.png")is relative to the source folder. so you have to place it in there.
you could also use absolute the file path to your desktop (sthg like "C:\Users\your.name\Desktop")
From the javadoc:
Creates an ImageIcon from the specified file. The image will be preloaded by using MediaTracker to monitor the loading state of the image. The specified String can be a file name or a file path. When specifying a path, use the Internet-standard forward-slash ("/") as a separator. (The string is converted to an URL, so the forward-slash works on all systems.) For example, specify:
new ImageIcon("images/myImage.gif")
As #Shriram mentioned, when you only specify the filename (with extension), it will search for that file in the current directory.
Hint: There exists an constructor overload which takes an URL as argument.

JavaFX WebView Downloading

I'm trying to add downloads to my Web Browser but the problem I got is to get the name of the file that you're trying to download. This is my code for downloading:
engine.locationProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
File file = new File(System.getProperty("user.home") + "/Downloads/Ekko Downloads/");
String[] downloadableExtensions = {".doc", ".xls", ".zip", ".exe", ".rar", ".pdf", ".jar", ".png", ".jpg", ".gif"};
for(String downloadAble : downloadableExtensions) {
if (newValue.endsWith(downloadAble)) {
try {
if(!file.exists()) {
file.mkdir();
}
File download = new File(file + "/" + newValue);
if(download.exists()) {
Dialogs.create().title("Exists").message("What you're trying to download already exists").showInformation();
return;
}
Dialogs.create().title("Downloading").message("Started Downloading").showInformation();
FileUtils.copyURLToFile(new URL(engine.getLocation()), download);
Dialogs.create().title("Download").message("Download is completed your download will be in: " + file.getAbsolutePath()).showInformation();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
});
The problem is here: File download = new File(file + "/" + newValue);
Instead of that newValue i need to get the name of that file.
Ideally what you would be doing is intercepting calls at the network layer, and interpreting the content disposition MIME messages embedded in the HTTP traffic. Those messages can instruct the browser to download the file as an attachment with a provided filename. That is how you end up with some files being automatically downloaded based on an instruction sent from the server when you click on a link a browser.
Another thing browsers do is implement a kind of mime magic where they look at either the mime content type of the returned message, a deep inspection of the network traffic or just the extension prefix of a URL location to invoke a handler to download specific content types (you are doing only the later in your code).
The last way browsers handle downloads is you can right click on a page or link and choose Save As.
So, if you wanted a really robust fully functional browser like Chrome or Firefox you would do all of the above. As this horribly complicated test matrix shows, it is not really a particularly easy thing to do for all corner cases and even the big guys get it wrong.
Intercepting network traffic for WebView is possible but difficult. You can research other StackOverflow questions to do that - I won't address it here.
The same is also true of intercepting arbitrary web clicks, again search StackOverflow and it will turn up some questions on that, which might allow you to get right click to download functionality working.
So you are left with just intercepting location property changes as you are doing - obviously not ideal, but workable for many scenarios. That means you don't get filenames encoded in the content-disposition header, instead you have to parse the location url (just grab everything after the last /) and set that as the filename.
You can use the answers to the following question to derive the filename from the location URL:
Get file name from URL
The WebView in JavaFX 8.0 will change status to "CANCELLED" when it cannot display a web page. This is generally an indication of a downloadable file, and you can inspect the location to make sure or filter what you want to download.
Next you can create a URL out of the location and do an HTTP HEAD request. This will allow you to get possible options for the filename based of the HTTP headers sent back. The headers may contain a header called Content-Disposition and the content may contain something like the following: attachment; filename="somfilename.ext".
So basically from there you can determine if you want to use the filename in the URL or the filename specified in the Content-Disposition header.

Define relative path in java eclipse?

I'm developing a dynamic web application in eclipse(mac), wherein I want to include a folder "templates" in the root directory (alongside src) which contains some template documents(temp1.docx, temp2.docx) which the app will edit whenever needed by the user. My plan is to copy temp1.docx to final.docx, make the required changes to it and finally output it. I'm trying to use the java Files.copy(source, dest) method to make a copy of the desired template document via the following code(servlet):
File source = new File("templates/temp1.docx");
File dest = new File("templates/final.docx");
Files.copy(source.toPath(), dest.toPath());
But I'm getting an exception that statesjava.nio.file.NoSuchFileException: templates/doc1.docx. I want to this app to be portable so I guess I'll have to use relative paths. Two questions-
1)Am I working on the correct lines? If so, how can I fix the error?
2)Is there another way to make it easier/better?
Thanks
Edit: using source.toPath() not source.getPath(); cc dest

Struts2: How to store images outside of the webapp and save its path to the db?

Until now I did saving image into the webapp directory and its path into database.
But now am trying to save the image outside of the webapp so that if I deploy my new war files then my old files folder will not be deleted.
From my below code my image file is correctly saving into the specified folder outside of the webapp but i don't know how to retrieve that image into my jsp page.
I tried like this
<img src="www.myproject.com/struts2project/files/smile.jpg/>"
but this is wrong. I am not getting my image to be display into my jsp page.
Below code is working fine for uploading image into absolute path but my problem is how to retrieve that image?
`fileSystemPath= "/files";
try{
File destFile = new File(fileSystemPath, thempicFileName);
FileUtils.copyFile(thempic, destFile);
String path=fileSystemPath+"/"+thempicFileName;
theme=dao.getThemeById(themId);
theme.setThemeScreenshot(path);
theme.setThemeName(theme.getThemeName());
theme.setThemeCaption(theme.getThemeCaption());
dao.saveOrUpdateTheme(theme);
}catch(IOException e){
e.printStackTrace();
return INPUT;
}`
Kindly help me...
I hope I'm being clear on what I need, let me know if I am not and I'll try to explain in another way.
As you say . . . this question describes what you need to do. I guess what you need to know is how to best achieve this with struts 2. Here's what's going on.
In your tag:
That url is being routed to your struts 2 application. Correct? The context is "struts2project".
One of the solutions offered by the referenced question is to use Tomcat's ability to serve static requests and configure tomcat to know about this other document root that holds your images. I think this is a great solution.
If you want to keep it inside of struts2, I think you're best option is to use a dedicated "image streaming from that other place" action that get's an InputStream to the image, then uses the Struts2 Stream Result result type. That result type lets you specify an adhoc InputStream. It also helps you set the appropriate headers. Note, the header values on that documentation page are for downloading the file, so you don't want those values. They would force the browser to open a save as dialog for the image, I think.
You are already using absolute paths, just use a location outside of your web application:
String destinationDir = "/path/to/my/directory/";
File file = new File(destinationDir + item.getName());

Loading files within android

Android seems to make life pretty easy for loading resources of certain types. Once I leave the beaten path a little bit, it seems less helpful. I can load in images, sounds and other objects from the assets folder if and only if they are of certain types. If I try to load a binary file of my own format, I get a less than helpful 'file not found' exception, even though listing the directory shows that it is clearly there.
I've tried using the following methods to read a binary file of a custom format from the assets directory:
File jfile = new File("file://android_asset/"+filename); //tried to get the URI of the assets folder
JarFile file = new JarFile("assets/"+filename); //tried assuming the assets folder is root
fd = am.openNonAssetFd( filename); //tried getting my file as an non asset in the assets folder (n.b. it is definitely there)
fs = am.open(filename, AssetManager.ACCESS_BUFFER); //tried loading it as an asset
I'm thinking that there's something fundamental about android file I/O that I don't understand yet. The documentation for asset management seems incomplete and there must be some reason for deliberately making this unintuitive (something to do with security?). So, what's the fool proof, canonical way of loading a binary file of my own format within an android app?
UPDATE:
I tried file:///android_asset/ but still no joy.
String fullfilename = "file:///android_asset/"+filename;
File jfile = new File(fullfilename);
if (jfile.exists())
{
return new FileInputStream(jfile);
}
else
{
return null; //the file does exist but it always says it doesn't.
}
Are there any permissions for the file or in the project manifest that I need?
Thanks
I think the best way to load a file from the Assets folder would be to use AssetManager.open(String filename) - this gives you back an InputStream which you can then wrap in a BufferedInputStream and otherwise call read() to get the bytes. This would work regardless of the file type. What kind of problems have you had with this approach specifically?
I think you have left out the slash as in
File jfile = new File("file:///android_asset/"+filename);
There's three forward slashes, not two. :)
For me the solution was to uninistall the application, clean the project in Eclipse and run it again. The problem was Android couldn't find the new files I put in the asset folder.
I ended up reading this question so I hope this can be helpful to someone else.

Categories