I have the following code for opening a local web page with a parameter:
String url = "file:///C:/work/my_page.html?";
String params = "message=HelloWorld";
Desktop.getDesktop().browse(new URI(url + params));
But, when the browser is opened, the parameters string (?message=HelloWorld) is removed.
While when I call some page with http:// prefix, it does work.
How can I make it work also with local file ? (i.e. such that starts with file:///)
You cannot.
http:// is one protocol which allows parameters.
file:// is another protocol which does not allow parameters.
Suggestion is - create local web site (for example jetty) and use http potocol only. BTW, all other http stuff like AJAX will not work either.
I found a workaround that solves it. It abuses the fact that from the browser, it's possible to redirect to another page with parameters, even though the target page is local.
Instead of calling the URL directly from Java, do the following:
Create a temporary HTML file. Into this temporary file print an HTML code that will automatically redirect the browser to the real URL you want to open. Example:
<meta http-equiv="refresh" content="0; url=file:///C:/work/my_page.html?message=helloWorld" />
Then, just launch the browser on the temp HTML file, which will immediately redirect you to the real URL :)
Here is the Java code for doing it in one line:
String url = "file:///C:/work/my_page.html?";
String params = "message=HelloWorld";
Desktop.getDesktop().browse(new URI(createHtmlLauncher(url + params)));
The method createHtmlLauncher():
private String createHtmlLauncher(String targetUrl) throws Exception {
String launcherFile = System.getProperty("java.io.tmpdir") + "local_launcher.html";
File launcherTempFile = new File(launcherFile);
PrintWriter writer = null;
try {
writer = new PrintWriter(launcherTempFile, "UTF-8");
} catch (Exception e) {
throw new Exception("Error opening file for writing: " + launcherTempFile.getAbsolutePath() + " : " + e.getMessage());
}
writer.println("<meta http-equiv=\"refresh\" content=\"0; url=" + targetUrl + "\" />");
writer.close();
return "file:///" + launcherFile.replace("\\", "/");
}
Note that for avoiding filling the disk with a lot of temp files, this code uses the same file for redirection each time. It means that if you open a few pages without any delay, you'll probably have race problems.
The solution is to use a generated temp file instead. The disadvantage of it is that you can't know when to remove these files from the disk. If you don't delete them and you have some extreme usage of the feature, the disk can get full.
Related
I have a html page saved locally with file path
"C:/Users/Kamil/git/RealSuperCoolTeam/src/main/resources/sfq.html"
I need to create a HtmlPage (gargoylesoftware libraries). However, when I pass my local file path into the function which would download the webpage I am receiving errors. It would normally work if passing in a hosted website link.
I have tried swapping the "/" to "\" but it doesn't seem to work.
textfieldSfqUrl.setText("C:/Users/Kamil/git/RealSuperCoolTeam/src/main/resources/sfq.html");
String url = textfieldSfqUrl.getText(); //url stores local file path
System.out.println("url : " + url);
HtmlPage page = client.getPage(url);
}
Expected result : HTML page is saved into the HtmlPage data structure
Actual Result : Throws many errors
Figured it out.
You must put "file:///" before the file path.
What would work:
file:///C:/Users/Kamil/git/RealSuperCoolTeam/src/main/resources/sfq.html
instead of
C:/Users/Kamil/git/RealSuperCoolTeam/src/main/resources/sfq.html
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.
I want to allow end-users of my site to download files from the server,
I tried to use the classic method using 2 jsp files :
index.jsp :
download the file
download.jsp :
<%
String filename = "file.xls";
String filepath = "C:\\Files\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\"");
java.io.FileInputStream fileInputStream=new java.io.FileInputStream(filepath + filename);
int i;
while ((i=fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
%>
But, it's not working with 2 Page Template in Fatwire 7.6.2,
Is that because I am not allowed to use reponse object in Fatwire ?
Using response object within a Sites (aka "fatwire") jsp is indeed discouraged. The typical way to make files available for download in Sites is to model the data in an asset, then use blobserver tags to render a url. See http://docs.oracle.com/cd/E29542_01/apirefs.1111/e39371/JSP/render-getbloburl.html for examples and other similar tags.
If you don't want to put these files into assets, then you may be better off not using blobserver tags and simply making them available directly through the webserver.
Phil
A webpage contains a link to an executable (i.e. If we click on the link, the browser will download the file on your local machine).
Is there any way to achieve the same functionality with Java?
Thank you
Yes there is.
Here a simple example:
You can have a JSF(Java Server Faces) page, with a supporting backing bean that contains a method annotated with #PostConstruct This means that any action(for example downloading), will occur when the page is created.
There is already a question very similar already, have a look at: Invoke JSF managed bean action on page load
You can use Java's, URL class to download a file, but it requires a little work. You will need to do the following:
Create the URL object point at the file
Call openStream() to get an InputStream
Open the file you want to write to (a FileOutputStream)
Read from the InputStream and write to the file, until there is no more data left to read
Close the input and output streams
It doesn't really matter what type of file you are downloading (the fact that it's an executable file is irrelevant) since the process is the same for any type of file.
Update: It sounds like what you actually want is to plug the URL of a webpage into the Java app, and have the Java app find the link in the page and then download that link. If that is the case, the wording of your question is very unclear, but here are the basic steps I would use:
First, use steps 1 and 2 above to get an InputStream for the page
Use something like TagSoup or jsoup to parse the HTML
Find the <a> element that you want and extract its href attribute to get the URL of the file you need to download (if it's a relative URL instead of absolute, you will need to resolve that URL against the URL of the original page)
Use the steps above to download that URL
Here's a slight shortcut, based on jsoup (which I've never used before, I'm just writing this from snippets stolen from their webpage). I've left out a lot of error checking, but hey, I usually charge for this:
Document doc = Jsoup.connect(pageUrl).get();
Element aElement = doc.getElementsByTag("a").first() // Obviously you may need to refine this
String newUrl = aElement.attr("abs:href"); // This is a piece of jsoup magic that ensures that the destination URL is absolute
// assert newUrl != null
URL fileUrl = new URL(newUrl);
String destPath = fileUrl.getPath();
int lastSlash = destPath.lastIndexOf('/');
if (lastSlash != -1) {
destPath = destPath.substring(lastSlash);
}
// Assert that this is really a valid filename
// Now just download fileUrl and save it to destPath
The proper way to determine what the destination filename should be (unless you hardcode it) is actually to look for the Content-Disposition header, and look for the bit after filename=. In that case, you can't use openStream() on the URL, you will need to use openConnection() instead, to get a URLConnection. Then you can use getInputStream() to get your InputStream and getRequestProperty("Content-Disposition") to get the header to figure out your filename. In case that header is missing or malformed, you should then fall-back to using the method above to determine the destination filename.
You can do this using apache commons IO FileUtils
http://commons.apache.org/io/apidocs/org/apache/commons/io/FileUtils.html#copyURLToFile(java.net.URL, java.io.File)
Edit:
I was able to successfully download a zip file from source forge site (it is not empty), It did some thing like this
import java.io.File;
import java.net.URL;
import org.apache.commons.io.FileUtils;
public class Test
{
public static void main(String args[])
{
try {
URL url = new URL("http://sourceforge.net/projects/gallery/files/gallery3/3.0.2/gallery-3.0.2.zip/download");
FileUtils.copyURLToFile(url, new File("test.zip"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I was able successfully download tomcat.exe too
URL url = new URL("http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.16/bin/apache-tomcat-6.0.16.exe");
I create ImageServlet to refer to videos out of my web application scope.
The location of all of my videos are on a intranet location that could be reached from any computer in the intranet:
String path = "\\myip\storage\ogg\VX-276.ogg"
In my application, when I write it as URL - it can't display it!
If I try to open it with chrome it automatically changes it to file://myip/storage/ogg/VX-276.ogg and the file is being displayed.
I tried to do so: file:////odelyay_test64/storage/ogg/
as well but Java converts the string to: file:\myip\storage\ogg\VX-276.ogg which does not exist!
What is the correct way to refer to it?
EDITED
I create a small test:
String path = "file://myip/storage/ogg/VX-276.ogg";
File file = new File(path);
if (file.exists())
System.out.println("exists");
else {
System.out.println("missing" + file.getPath());
}
and I get:
missing file:\myip\storage\ogg\VX-276.ogg
As you can see the slashes are being switched
As per your previous question, you're referencing the resource in a HTML <video> tag. All URLs in the HTML source code must be http:// URLs (or at least be relative to a http:// URL). Most browsers namely refuse to load resources from file:// URLs when the HTML page is itself been requested by http://. You just need to let the URL point to the servlet. If the servlet's doGet() method get hit, then the URL is fine and you should not change it.
Your concrete problem is in the way how you open and read the desired file in the servlet. You need to ensure that the path in File file = new File(path) points to a valid location before you open a FileInputStream on it.
String path = "file://myip/storage/ogg/VX-276.ogg";
File file = new File(path);
// ...
If the servlet code is well written that it doesn't suppress/swallow exceptions and you have read the server logs, then you should have seen an IOException such as FileNotFoundException along with a self-explaining message in the server logs whenever reading the file fails. Go read the server logs.
Update as per the comments, it turns out that you're using Windows and thus file:// on a network disk isn't going to work for Java without mapping it on a drive letter. You need to map //myip on a drive letter first, for example X:.
String path = "X:/storage/ogg/VX-276.ogg";
File file = new File(path);
// ...
in the end I used VFS library of apache and my code looks like this:
public static void main(String[] args) {
FileSystemManager fsManager = null;
String path = "\\\\myip\\storage\\ogg\\VX-276.ogg";
try {
fsManager = VFS.getManager();
FileObject basePath;
basePath = fsManager.resolveFile("file:" + path);
if (basePath.exists())
System.out.println("exists");
else {
System.out.println("missing" + basePath.getURL());
}
} catch (FileSystemException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
In this way, I don't need to create a driver for each user of the system and it allows me not to depend on operation system!