Running phantomjs as local resource when using jar executable
Need a little help with this. My goal is to have a jar executable that takes a screen capture of a web page and works on both windows and Linux machines. I tried using html2image but the results from phantomjs were exponentially better. I have some code that looks like this:
RESOURCE_PATH = MyClass.class.getClassLoader().getResource("resources").getPath();
public static void main (String[] args) {
String url = args[1];
String outFilePath = args[0];
final String phantomjsHome = RESOURCE_PATH + "/phantomjs/";
ProcessBuilder pb = new ProcessBuilder(phantomjsHome + "phantomjs.exe", phantomjsRasterizeScript, url, outFilePath);
Process process = pb.start();
process.waitFor();
}
Now I have tests that reassure me, when I run this as a java application, it works great, but when I create an executable jar, I get an error. I have checked and double checked that RESOURCE_FOLDER is pointing to the correct location. But when I run the jar using
java -jar MyProject.jar "google.png" "https://google.com"
I get
java.io.Exception: Cannot run program "file:/C:/Users/Joe/MyProject.jar/resources/phantomjs.exe": CreateProcess error=2, The system cannot find file specified
BTW, this is my first question asking a question on SO, so if you need more information or have any suggestions or comments about the comment phrase. Thank!
UPDATE
After some searching, I found that the executable could not be executed from inside the jar. I created a method for copying an executable outside of the jar that seems to work.
private static String loadPhantomJS() {
String phantomJs = "phantomjs.exe";
try {
InputStream in = WebShot.class.getResourceAsStream("/resources/phantomjs/" + phantomJs);
File fileOut = new File(storePath + phantomJs);
OutputStream out = FileUtils.openOutputStream(fileOut);
IOUtils.copy(in, out);
in.close();
out.close();
return fileOut.getAbsolutePath();
} catch (Exception e) {
return "";
}
}
note that this method only works for windows, changes the file path for linux.
source to share
The above method works for Windows machines, please note that any file you want to run must also be unpacked outside of the jar file. A similar method for loadPhantomJS
can be used to unpack other resource files from the jar file. I used this method:
private static void makeLocalFile(String outPath, InputStream is) {
try {
InputStream is;
File fileOut = new File(outPath);
OutputStream out;
out = FileUtils.openOutputStream(fileOut);
IOUtils.copy(in, out);
in.close();
out.close();
} catch (Exception e) {
System.out.println(e);
}
}
I am getting InputStream
from my resources using MyClass.class.getResourceAsStream("jsFile.js")
. The only way I have been able to get it to work so far on linux is to actually install the phantomjs
linux installation. This answer will be updated if / when I find a better solution.
source to share