How to upload a file using af:inputFile in Oracle ADF - java

Can anyone please tell me how to upload file to server using af:inputFile in Oracel ADF. I searched about this and found we can use the following
<af:form usesUpload="true">
<af:inputFile columns="10"
valueChangeListener="#{backing.fileUploaded}"/>
</af:form>
using the above code I can set a method that executes when some choose some file in the form. So now I need to know in fileUploaded method what should be the java code to upload the given file to the server.
Please help me. How I can achieve this.
Thanks in advance.

As you have already created value change listener in managed bean then use this code -
/**Method to Upload File ,called on ValueChangeEvent of inputFile
* #param vce
*/
public void uploadFileVCE(ValueChangeEvent vce) {
if (vce.getNewValue() != null) {
//Get File Object from VC Event
UploadedFile fileVal = (UploadedFile) vce.getNewValue();
}
}
and this is the method to upload file on server (You have to provide absolute path)
/**Method to upload file to actual path on Server*/
private String uploadFile(UploadedFile file) {
UploadedFile myfile = file;
String path = null;
if (myfile == null) {
} else {
// All uploaded files will be stored in below path
path = "D://FileStore//" + myfile.getFilename();
InputStream inputStream = null;
try {
FileOutputStream out = new FileOutputStream(path);
inputStream = myfile.getInputStream();
byte[] buffer = new byte[8192];
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.flush();
out.close();
} catch (Exception ex) {
// handle exception
ex.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
}
}
}
//Returns the path where file is stored
return path;
}
Check this thread on OTN Forum
https://community.oracle.com/message/13135474#13135474
Here you can read full implementation and download sample application to test
http://www.awasthiashish.com/2014/08/uploading-and-downloading-files-from.html
Full disclosure on the last link above and its contents: I wrote it and it is my TLD.

Your inputFile should look something like the following where gciuiCheckin is a reference to the backing bean. In this case the inputFile control is in a jsff contained as a region inside a jspx with usesUpload="true", but this would be similar if you are putting your controls directly in the jspx, the main thing is you need to bind the control value to a backing bean variable of type UploadedFile:
<af:inputFile label=" " id="ifDoc" columns="50"
value="#{pageFlowScope.gciuiCheckin.filesToUpload}"
maximumFiles="#{pageFlowScope.gciuiCheckin.maxFilesCanBeUploaded}"
autoHeightRows="0" rows="5" uploadType="auto"/>
Then you also should have a commandButton to call a bean method once user has selected the file (each file typically is uploaded to server as the user selects or drag drops each one):
<af:commandButton text="Commit File(s)" id="cbUpload"
partialSubmit="true" action="#{pageFlowScope.gciuiCheckin.saveUploadedFilesAction}"/>
You will need this import in the backing bean:
import org.apache.myfaces.trinidad.model.UploadedFile;
In the backing bean, create a List with accessors to hold the uploaded files:
private List<UploadedFile> filesToUpload;
In the method called by the commandButton, you will do something like:
public String saveUploadedFilesAction() {
List<UploadedFile> files = this.getFilesToUpload();
if (files == null || files.size() == 0) {
displayMessageToUser(FacesMessage.SEVERITY_WARN, checkinErrorMessage);
return null;
}
//iterate each file and check size, extension, etc...
for (int i = 0; i < files.size(); i++) {
UploadedFile currFile = files.get(i);
//now do something with the file...
}
...
Hope this helps.

Related

Context getRealPath() for non-existent file

Can someone explain what is the difference between the following two calls to ServletContext getRealPath() in Tomcat:
context.getRealPath("/") + "\\songModified.wav";
context.getRealPath("/" + "\\songModified.wav");
I have a very simple GET method on the server which reads a file on the server and copies the bytes into a new file in the location returned by the above call.
On the client side I have an audio tag that references an audio file on the server, calls this method that creates a new file and changes the reference of the audio tag to this new file. The thing is that in the javascript callback this new file is not immediately referenceable if I store the file to the path that is returned from the second case of the above getRealPath call. Basically it returns a 404. If I store it to the returned path of the first case of the call then it is immediately referenceable and the audio tag normaly references the new file.
Both of those calls to getRealPath() return exactly the same string:
C:\Users\Mihael\apache-tomcat-9.0.31\wtpwebapps\AudioSimulator\songModified.wav
I am passing this returned string to the FileOutputStream constructor further in the code.
Thing to note here is that this file does not exist at the moment of the getRealPath() call so I am confused why is it returning anything at all in the second case of the call.
I know this is not the recommended way of storing files so I am asking from a purely educational perspective. How can the second call to this method break my functionality if they both return exactly the same string to the rest of the code?
EDIT:
Here is a very simple Javascript and Java code for anyone who wants to test this.
Javascript:
<body>
<script>
function modifyRequest() {
var xhttp = new XMLHttpRequest();
xhttp.onload = function() {
var audio = document.getElementById("player");
var currentTime = audio.currentTime;
audio.src = "http://localhost:8080/AudioSimulator/bluesModified.wav";
audio.currentTime = currentTime;
audio.play();
};
xhttp.open("GET", "http://localhost:8080/AudioSimulator/rest/Test/testPath");
xhttp.send();
}
</script>
<audio id="player" src="http://localhost:8080/AudioSimulator/blues.wav"
controls>
Your browser does not support the
<code>audio</code> element.
</audio>
<button onclick="modifyRequest()">Test</button>
</body>
Java:
#Path("/Test")
public class Test {
#Context
ServletContext context;
#GET
#Path("/testPath")
public Response testPath() {
File fileIn = new File(context.getRealPath("/") + "\\blues.wav");
File fileOut = new File(context.getRealPath("/" + "\\bluesModified.wav"));
//if i write it like this it would work
//File fileOut = new File(context.getRealPath("/") + "\\bluesModified.wav");
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(fileIn);
fos = new FileOutputStream(fileOut);
byte[] inArray = new byte[(int) fileIn.length()];
try {
fis.read(inArray);
fos.write(inArray);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return Response
.ok()
.entity("Success")
.header("Access-Control-Allow-Origin", "null")
.build();
}
}
I have taken the time to dive into Tomcat source to find the cause for this. It turns out that getRealPath, in addition to retrieving the system path for a given virtual path, also works a bit with the Tomcat cache.
NOTE:
I know that my file separator usage is not good, but Tomcat is smart enough to validate the above call to produce /bluesModified.wav. So even if I call it like #rickz mentioned in the comments, the result would be the same and therefore that was not the issue.
The issues I had with being unable to reference the file in the case of the following call
context.getRealPath("/" + "\\bluesModified.wav")
was the fact that in this case we are passing the file path to the method, while in the case that works we are passing in the directory path.
What happens is that the call to getRealPath() first checks the cache for the existence of the resource identified by the webapppath /bluesModified.wav. Since it does not exist at the moment of the call, Tomcat will create an instance of the EmptyResource class which is basically a wrapper around File class and represents a file that does not exist, and it will then store the reference to this file in its cache.
The issue here is that even though I create a file that will have the correct virtual path Tomcat will still have that empty resource representing a non existent file in its cache. In other words, if I reference the file from the client side like so
http://localhost:8080/AudioSimulator/bluesModified.wav
Tomcat will return the cached resource that represents the empty file, which actually means a 404 to the client even though the file exists.
Waiting for 5 seconds, which is the time to live of Tomcat cache entries, and then trying to reference the file will revalidate the cache entry and produce a FileResource instead of EmptyResource in which case the referencing will work normally.
It works in this case
context.getRealPath("/") + "\\bluesModified.wav"
since the path that is getting cached is a directory and the file name is simply concatenated. So the string I have here is just an absolute path to the file I am going to create with no cache entries colliding with it.
My mistake was assuming that getRealPath() is just some "pure" method that will return a string I can use to create files while in fact it has a bit of side effects. These side effects are not documented and even though I might have done some things incorrectly the bottom line is this method is not that predictable to use when doing File IO stuff.
The String returned by getRealPath from the ServletContext implementation is normalized.
So when you call getRealPath("/") + "\blues.wav") only the String "/" is normalized, and the String concatenation "\blues.wav" is not.
But when you call getRealPath("/" + "\blues.wav")) the full concatened String is normilized.
public String getRealPath(String path) {
if ("".equals(path)) {
path = "/";
}
if (this.resources != null) {
try {
WebResource resource = this.resources.getResource(path);
String canonicalPath = resource.getCanonicalPath();
if (canonicalPath == null) {
return null;
}
if ((resource.isDirectory() && !canonicalPath.endsWith(File.separator) || !resource.exists()) && path.endsWith("/")) {
return canonicalPath + File.separatorChar;
}
return canonicalPath;
} catch (IllegalArgumentException var4) {
}
}
return null;
}
You can see WebResource resource = this.resources.getResource(path) will try to validate your path and will return a validated path :
private String validate(String path) {
if (!this.getState().isAvailable()) {
throw new IllegalStateException(sm.getString("standardRoot.checkStateNotStarted"));
} else if (path != null && path.length() != 0 && path.startsWith("/")) {
String result;
if (File.separatorChar == '\\') {
result = RequestUtil.normalize(path, true);
} else {
result = RequestUtil.normalize(path, false);
}
if (result != null && result.length() != 0 && result.startsWith("/")) {
return result;
} else {
throw new IllegalArgumentException(sm.getString("standardRoot.invalidPathNormal", new Object[]{path, result}));
}
} else {
throw new IllegalArgumentException(sm.getString("standardRoot.invalidPath", new Object[]{path}));
}
}

Load current class into JarOutputStream

I am building an application that must load the current class at runtime, and add it to a different .jar that I am creating. I have a method that adds files to a jar.
private static void add(File source, JarOutputStream target,
Manifest manifest) throws IOException {
BufferedInputStream in = null;
try {
String name = source.getName();
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true) {
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
} finally {
if (in != null)
in.close();
}
}
My problem is this: I can't seem to find out how to add the current class into a file at runtime. I have tried this:
File classFile= new File(getClass().getResource("MyClass.class").getPath());
but I get a null pointer exception. Any help would be greatly appreciated.
Don't try to get the class file as a File - just fetch the stream directly:
InputStream classFile = getClass().getResourceAsStream("MyClass.class");
You'll need to modify your add method to take a target name and an input stream, of course. (Potentially overload it, so you've still got the existing method available, which would just open the file, call the other method, then close the stream.)

Retrieve the web app root path in JSF Managed Bean

Im trying to access the example/web folder (see below in the image) in a jsf managed bean but cant seem to find a way to do it
thx
Try
FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath()
for build relative url's to resources in your app.
If you want the real path...
ServletContext ctx = (ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext();
String realPath = ctx.getRealPath("/");
If you want to get it as a File for some reason, then you need ExternalContext#getRealPath(). This converts a relative web path to an absolute disk file system. Since you need the web's root folder, just pass in /:
String absoluteWebPath = externalContext.getRealPath("/");
File webRoot = new File(absoluteWebPath);
// ...
Unrelated to the concrete problem, whatever functional requirement you've had in mind for which you thought that having an absolute local disk file system path to the web folder is the right solution, it has most definitely to be solved differently. And indeed, as per your comment on the other answer,
because Im trying to upload some file inside the folder and using the relative path
you're going the wrong path. You should not store uploaded files in there if you intend to keep them longer than the webapp's deployment lifetime. Whenever you redeploy the webapp (and on some server configs even when you restart the server), the uploaded files would get completely lost, simply because they are not contained as part of the original WAR file. Even more, some heavy server configs don't expand the WAR on disk at all, but in memory instead, the getRealPath() would then always return null.
Rather store it in a fixed disk file system path outside the server's deploy folder. Add that path in turn as a new server context or docroot, so that it's accessible on a different (virtual) context path. Or homegrow a servlet which gets an InputStream of it from disk and writes it to OutputStream of the response. See also this related answer: Uploaded image only available after refreshing the page
Try:
String relativePath="/resources/temp/";
String absolutePath= FacesContext.getCurrentInstance.getExternalContext().getRealPath(relativePath);
File file = new File(absolutePath);
to get real path.
Create a tmp file in resources/temp/ to avoid any exception.
Just wanted to thank Balus C. Code Java with JSP, in Tomcat/Tomee server I the following code that works:
private Boolean SaveUserItemImage(Part ui, String bid) throws IOException {
Boolean fileCreate = false;
OutputStream out = null;
InputStream filecontent = null;
ExternalContext ctx = context().getExternalContext();
String absoluteWebPath = ctx.getRealPath("/");
String resource_path = absoluteWebPath + "\\resources\\";
String image_path = resource_path + "\\" + this.itemType + "_images\\";
String buildFileName = image_path + bid + "_" + getFileName(ui);
File files = null;
try {
files = new File(buildFileName);
fileCreate = true;
} catch (Exception ex) {
System.out.println("Error in Creating New File");
Logger.getLogger(ItemBean.class.getName()).log(Level.SEVERE, null, ex);
}
if (fileCreate == true) {
if (files.exists()) {
/// User may be using same image file name but has been editted
files.delete();
}
try {
out = new FileOutputStream(files);
filecontent = ui.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
while ((read = filecontent.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
fileCreate = true;
} catch (FileNotFoundException fne) {
fileCreate = false;
Logger.getLogger(ItemBean.class.getName()).log(Level.SEVERE, "SaveUserItemImage", fne);
} finally {
if (out != null) {
out.close();
}
if (filecontent != null) {
filecontent.close();
}
files = null;
}
}
return fileCreate;
}

How to copy file inside jar to outside the jar?

I want to copy a file from a jar. The file that I am copying is going to be copied outside the working directory. I have done some tests and all methods I try end up with 0 byte files.
EDIT: I want the copying of the file to be done via a program, not manually.
First of all I want to say that some answers posted before are entirely correct, but I want to give mine, since sometimes we can't use open source libraries under the GPL, or because we are too lazy to download the jar XD or what ever your reason is here is a standalone solution.
The function below copy the resource beside the Jar file:
/**
* Export a resource embedded into a Jar file to the local file path.
*
* #param resourceName ie.: "/SmartLibrary.dll"
* #return The path to the exported resource
* #throws Exception
*/
static public String ExportResource(String resourceName) throws Exception {
InputStream stream = null;
OutputStream resStreamOut = null;
String jarFolder;
try {
stream = ExecutingClass.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
if(stream == null) {
throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
}
int readBytes;
byte[] buffer = new byte[4096];
jarFolder = new File(ExecutingClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath().replace('\\', '/');
resStreamOut = new FileOutputStream(jarFolder + resourceName);
while ((readBytes = stream.read(buffer)) > 0) {
resStreamOut.write(buffer, 0, readBytes);
}
} catch (Exception ex) {
throw ex;
} finally {
stream.close();
resStreamOut.close();
}
return jarFolder + resourceName;
}
Just change ExecutingClass to the name of your class, and call it like this:
String fullPath = ExportResource("/myresource.ext");
Edit for Java 7+ (for your convenience)
As answered by GOXR3PLUS and noted by Andy Thomas you can achieve this with:
Files.copy( InputStream in, Path target, CopyOption... options)
See GOXR3PLUS answer for more details
Given your comment about 0-byte files, I have to assume you're trying to do this programmatically, and, given your tags, that you're doing it in Java. If that's true, then just use Class.getResource() to get a URL pointing to the file in your JAR, then Apache Commons IO FileUtils.copyURLToFile() to copy it out to the file system. E.g.:
URL inputUrl = getClass().getResource("/absolute/path/of/source/in/jar/file");
File dest = new File("/path/to/destination/file");
FileUtils.copyURLToFile(inputUrl, dest);
Most likely, the problem with whatever code you have now is that you're (correctly) using a buffered output stream to write to the file but (incorrectly) failing to close it.
Oh, and you should edit your question to clarify exactly how you want to do this (programmatically, not, language, ...)
Faster way to do it with Java 7+ , plus code to get the current directory:
/**
* Copy a file from source to destination.
*
* #param source
* the source
* #param destination
* the destination
* #return True if succeeded , False if not
*/
public static boolean copy(InputStream source , String destination) {
boolean succeess = true;
System.out.println("Copying ->" + source + "\n\tto ->" + destination);
try {
Files.copy(source, Paths.get(destination), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
logger.log(Level.WARNING, "", ex);
succeess = false;
}
return succeess;
}
Testing it (icon.png is an image inside the package image of the application):
copy(getClass().getResourceAsStream("/image/icon.png"),getBasePathForClass(Main.class)+"icon.png");
About the line of code (getBasePathForClass(Main.class)): -> check the answer i have added here :) -> Getting the Current Working Directory in Java
Java 8 (actually FileSystem is there since 1.7) comes with some cool new classes/methods to deal with this. As somebody already mentioned that JAR is basically ZIP file, you could use
final URI jarFileUril = URI.create("jar:file:" + file.toURI().getPath());
final FileSystem fs = FileSystems.newFileSystem(jarFileUri, env);
(See Zip File)
Then you can use one of the convenient methods like:
fs.getPath("filename");
Then you can use Files class
try (final Stream<Path> sources = Files.walk(from)) {
sources.forEach(src -> {
final Path dest = to.resolve(from.relativize(src).toString());
try {
if (Files.isDirectory(from)) {
if (Files.notExists(to)) {
log.trace("Creating directory {}", to);
Files.createDirectories(to);
}
} else {
log.trace("Extracting file {} to {}", from, to);
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException e) {
throw new RuntimeException("Failed to unzip file.", e);
}
});
}
Note: I tried that to unpack JAR files for testing
Robust solution:
public static void copyResource(String res, String dest, Class c) throws IOException {
InputStream src = c.getResourceAsStream(res);
Files.copy(src, Paths.get(dest), StandardCopyOption.REPLACE_EXISTING);
}
You can use it like this:
File tempFileGdalZip = File.createTempFile("temp_gdal", ".zip");
copyResource("/gdal.zip", tempFileGdalZip.getAbsolutePath(), this.getClass());
Use the JarInputStream class:
// assuming you already have an InputStream to the jar file..
JarInputStream jis = new JarInputStream( is );
// get the first entry
JarEntry entry = jis.getNextEntry();
// we will loop through all the entries in the jar file
while ( entry != null ) {
// test the entry.getName() against whatever you are looking for, etc
if ( matches ) {
// read from the JarInputStream until the read method returns -1
// ...
// do what ever you want with the read output
// ...
// if you only care about one file, break here
}
// get the next entry
entry = jis.getNextEntry();
}
jis.close();
See also: JarEntry
To copy a file from your jar, to the outside, you need to use the following approach:
Get a InputStream to a the file inside your jar file using getResourceAsStream()
We open our target file using a FileOutputStream
We copy bytes from the input to the output stream
We close our streams to prevent resource leaks
Example code that also contains a variable to not replace the existing values:
public File saveResource(String name) throws IOException {
return saveResource(name, true);
}
public File saveResource(String name, boolean replace) throws IOException {
return saveResource(new File("."), name, replace)
}
public File saveResource(File outputDirectory, String name) throws IOException {
return saveResource(outputDirectory, name, true);
}
public File saveResource(File outputDirectory, String name, boolean replace)
throws IOException {
File out = new File(outputDirectory, name);
if (!replace && out.exists())
return out;
// Step 1:
InputStream resource = this.getClass().getResourceAsStream(name);
if (resource == null)
throw new FileNotFoundException(name + " (resource not found)");
// Step 2 and automatic step 4
try(InputStream in = resource;
OutputStream writer = new BufferedOutputStream(
new FileOutputStream(out))) {
// Step 3
byte[] buffer = new byte[1024 * 4];
int length;
while((length = in.read(buffer)) >= 0) {
writer.write(buffer, 0, length);
}
}
return out;
}
A jar is just a zip file. Unzip it (using whatever method you're comfortable with) and copy the file normally.
${JAVA_HOME}/bin/jar -cvf /path/to.jar

How to use java.util.zip to archive/deflate string in java for use in Google Earth?

Use Case
I need to package up our kml which is in a String into a kmz response for a network link in Google Earth. I would like to also wrap up icons and such while I'm at it.
Problem
Using the implementation below I receive errors from both WinZip and Google Earth that the archive is corrupted or that the file cannot be opened respectively. The part that deviates from other examples I'd built this from are the lines where the string is added:
ZipEntry kmlZipEntry = new ZipEntry("doc.kml");
out.putNextEntry(kmlZipEntry);
out.write(kml.getBytes("UTF-8"));
Please point me in the right direction to correctly write the string so that it is in doc.xml in the resulting kmz file. I know how to write the string to a temporary file, but I would very much like to keep the operation in memory for understandability and efficiency.
private static final int BUFFER = 2048;
private static void kmz(OutputStream os, String kml)
{
try{
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(os);
out.setMethod(ZipOutputStream.DEFLATED);
byte data[] = new byte[BUFFER];
File f = new File("./icons"); //folder containing icons and such
String files[] = f.list();
if(files != null)
{
for (String file: files) {
LOGGER.info("Adding to KMZ: "+ file);
FileInputStream fi = new FileInputStream(file);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(file);
out.putNextEntry(entry);
int count;
while((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
}
ZipEntry kmlZipEntry = new ZipEntry("doc.kml");
out.putNextEntry(kmlZipEntry);
out.write(kml.getBytes("UTF-8"));
}
catch(Exception e)
{
LOGGER.error("Problem creating kmz file", e);
}
}
Bonus points for showing me how to put the supplementary files from the icons folder into a similar folder within the archive as opposed to at the same layer as the doc.kml.
Update Even when saving the string to a temp file the errors occur. Ugh.
Use Case Note The use case is for use in a web app, but the code to get the list of files won't work there. For details see how-to-access-local-files-on-server-in-jboss-application
You forgot to call close() on ZipOutputStream. Best place to call it is the finally block of the try block where it's been created.
Update: To create a folder, just prepend its name in the entry name.
ZipEntry entry = new ZipEntry("icons/" + file);

Categories