Send full client side file path to server side using p:fileUpload - jsf

I'm using:
PrimeFaces 5.0
GlassFish 4.1
Netbeans 8.0.2
My case: I have an intranet web application where I'd like to let the client browse the intranet network disk file system and send the full client side file path to the server side. In other words, I do not need the file contents, but only the full file path, as it is in the intranet network.
I tried using <p:fileUpload> for this:
public void handleFileUpload(FileUploadEvent event) throws IOException {
UploadedFile uploadedFile = event.getFile();
InputStream inputStream = uploadedFile.getInputstream();
File file = new File(uploadedFile.getFileName());
System.out.println(file.getAbsolutePath());
String realPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/");
System.out.println(realPath);
}
The file.getAbsolutePath() prints the following:
C:\Users\XXX\AppData\Roaming\NetBeans\8.0.2\config\GF_4.1\domain1\config\file.txt
And, the realPath prints the following:
C:\Users\XXX\Documents\NetBeansProjects\PROJECT\dist\gfdeploy\PROJECT\PROJECT-war_war\
However, I'm expecting to see
\\MACHINE\Documents\file.txt
How can I achieve this?

You're basically looking in the wrong direction for the solution. And, you're looking at JSF/PrimeFaces in a wrong way. JSF is in the context of this question just a HTML code generator.
HTML does not support sending full client side file path to the server side. True, older Internet Explorer versions had the awkward security bug that the full client side file path was sent along the file name. But, this is not mandated by HTML. The sole purpose of <input type="file"> is to send the file content from client to server, which you're supposed to read via getInputStream() and save on a fixed location yourself. The filename is here just additional metadata. This is usually never used as-is to save the file in the server, to avoid overwrites by other uploads with coincidentally the same filename. The file name is at most used as prefix of the final file name in the server side, or only remembered in order to be redisplayed in "Save As" during a download. But that's it.
All your attempts failed because here,
File file = new File(uploadedFile.getFileName());
System.out.println(file.getAbsolutePath());
.. the getFileName() only returns the file name, not the file path. The new File(...) constructor will interpret the file name relative to the "current working directory", i.e. the directory which was open at the moment the JVM (in your case, the server), was started. Basically, you're attempting to locate a non-existing file. The actual file is stored elsewhere, usually in the OS-managed temporary file location beyond your control. However, this is also not what you're looking for.
And here,
String realPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/");
System.out.println(realPath);
.. the getRealPath() only converts the webcontent-relative path to absolute disk file system path. In other words, it gives you the path to the deploy folder where all contents of the expanded WAR file are stored. Usually it are the XHTML/JS/CSS files and such. This is also definitely not what you're looking for. Moreover, there is no single sensible real world use case for getRealPath(). You should absolutely avoid using it.
You need to look for the solution in a different direction than HTML. You need a client side application capable of grabbing the full client side file path and then sending it to the server side. HTML can't do it (even not HTML5). CSS can't do it. JS can't do it. But Java can do it. You can use Swing JFileChooser to browse and pick the actual File. You only need to execute it in the client side instead of the server side. You can use an Applet for this which you in turn can easily embed in any webpage, even a JSF page; you know, it's just a HTML code generator.
Basically:
In applet, grab full file path via JFileChooser.
JFileChooser fileChooser = new JFileChooser();
if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
String selectedFileAbsolutePath = selectedFile.getAbsolutePath();
// ...
} else {
// User pressed cancel.
}
Additional advantage is, you can use FileSystemView to restrict it to certain (network) drives or folders, so that the enduser won't accidentally select completely irrelevant drives/folders.
Send the full file path as query parameter via URLConnection to server side.
String url = "/someServletURL?selectedFileAbsolutePath=" + URLDecoder.decode(selectedFileAbsolutePath, "UTF-8");
URLConnection connection = new URL(getCodeBase(), url).openConnection();
connection.setRequestProperty("Cookie", "JSESSIONID=" + getParameter("sessionId"));
InputStream response = connection.getInputStream();
// ...
Read it in a servlet.
#WebServlet("/someServletURL")
public class SomeServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest request, HttpServletResponse resposne) throws ServletException, IOException {
String selectedFileAbsolutePath = request.getParameter("selectedFileAbsolutePath");
// ...
}
}
Don't forget to pass session ID as applet parameter when embedding the applet in JSF page.
<applet ...>
<param name="sessionId" value="#{session.id}" />
</applet>
This way the servlet will have access to exactly the same HTTP session as the JSF page, and then you can share/communicate data between them.

Related

X-Pages: fileUpload control preventing unwanted files from being uploaded

I am using the accept property in the fileUpload control to only allow certain file Types and prevent uploading .exe or other potentially harmful files.
application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/pdf,text/plain,image/gif,image/jpeg,image/pjpeg,image/png"
This works, however I am using a Tool called Burp Suite that allows me to intercept an acceptable file eg .txt that could contain harmful code and change the filename extension to .exe which is then upload to the X-Page database.
When I goto save the document and after Interception and changing to a .exe, I have added the following code to identify an exe file:
Can we manipulate what has been uploaded and change the file extension to a harmless .txt ?
var fileData:com.ibm.xsp.http.UploadedFile =facesContext.getExternalContext().getRequest().getParameterMap().get(getClientId('fileUpload1'));
if (fileData != null) {
var tempFile:java.io.File = fileData.getServerFile();
// Get the path
var filePath:String = tempFile.getParentFile().getAbsolutePath();
// Get file Name
var fileName:String = tempFile.getParentFile().getName();
// Get the Name of the file as it appeared on the client machine - the name on the server will NOT be the same
var clientFileName:String = fileData.getClientFileName();
}
var fileRight = clientFileName.slice(-4);
if (fileRight == ".exe")
{
//facesContext.getExternalContext().getRequest().getParameterMap().get(getClientId('fileUpload1').replace(".exe",".txt"))
//facesContext.getExternalContext().getRequest().getParameterMap().get(getClientId('fileUpload1').remove(".exe",0))
}
Yes, you can. You have on the properties of control two options 'Use original file name of uploaded file' and 'Replace file name of uploaded file...' where you can put name with extension 'name.txt' . I didn't try to change only extension... That is probably better in code to replace.

Store PDF for a limited time on app server and make it available for download

Hei there, I'm using PrimeFaces 5/JSF 2 and tomcat!
Can someone show me or give me an idea on how to store pdfs for a limited time on an application server(I'm using tomcat) and then download it (if that's what the user requests). This functionality relates to invoices so I can't use the dataExporter.
To be more specific, I pretty much implemented this but I don't feel so sure about it. One big question is... where do I store my generated files? I've browsed around and people said that it's not ok to save the files in the webApp or in the tomcat directory. What other solutiuon do I have?
Make use of File#createTempFile() facility. The servletcontainer-managed temporary folder is available as application scoped attribute with ServletContext.TEMPDIR as key.
String tempDir = (String) externalContext.getApplicationMap().get(ServletContext.TEMPDIR);
File tempPdfFile = File.createTempFile("generated-", ".pdf", tempDir);
// Write to it.
Then just pass the autogenerated file name around to the one responsible for serving it. E.g.
String tempPdfFileName = tempPdfFile.getName();
// ...
Finally, once the one responsible for serving it is called with the file name as parameter, for example a simple servlet, then just stream it as follows:
String tempDir = (String) getServletContext().getAttribute(ServletContext.TEMPDIR);
File tempPdfFile = new File(tempDir, tempPdfFileName);
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(tempPdfFile.length()));
response.setHeader("Content-Disposition", "inline; filename=\"generated.pdf\"");
Files.copy(tempPdfFile.toPath(), response.getOutputStream());
See also:
How to save generated file temporarily in servlet based web application
Recommended way to save uploaded files in a servlet application
Your question is vague, but if my understanding is good:
First if you want to store the PDF for a limited time you can create a job that clean you PDFs every day or week or whatever you need.
For the download side, you can use <p:fileDownload> (http://www.primefaces.org/showcase/ui/file/download.xhtml) to download any file from the application server.

How to get the uploaded file path in JSF

I'm importing Excel document for reading and displaying the content in the UI. I need to know how to get the path of the file uploaded using browse in order to read the content of the excel file.
I need to know how to get the path of the file uploaded using browse in order to read the content of the excel file.
There's a major thinking mistake here.
Imagine that I am the client who want to upload the file and that you are the server who need to get the file's contents. I give you the path c:\path\to\foo.xls as sole information. How would you as being the server ever get its contents? Do you have an open TCP/IP connection to my local hard disk file system? Really? Is everyone else's local disk file system with all that sensitive information really so easily accessible by Internet?
That isn't how uploading files works. This would only ever work if the server runs at physically the same machine as the client, so that you can just use FileInputStream with that path (which would only occur in local development environment).
You should instead be interested in the sole file contents which the client has sent to you along with the HTTP request body. In HTML terms, you can use <input type="file"> for this. But until the upcoming JSF 2.2 there is no equivalent standard JSF <h:xxx> component for this. You need to look for JSF component libraries offering a component for this. In your case, with RichFaces (as tagged in your question), you can use <rich:fileUpload> for this. It's unclear which RichFaces version you're using, but for RF 3.3.3 you can find a complete example in the 3.3.3 showcase site and for RF 4.0 in the 4.0 showcase site.
Whatever way you choose, you should in your JSF managed bean ultimately end up with a byte[] or an InputStream representing the file contents. Then you've all the freedom to store it wherever you want on the server's local disk file system using for example FileOutputStream. You can even also just feed it directly to whatever Excel API you're using, most of them have just a method taking an InputStream or byte[].
you better take a look at this article. The solution that uses Tomahawk 2.0 ( http://myfaces.apache.org/tomahawk-project/tomahawk20/index.html ) by BalusC is great
JSF 2.0 File upload
Everything you need is there
String fileName = FilenameUtils.getName(uploadedFile.getName());
byte[] bytes = uploadedFile.getBytes();
FileOutputStream outputStream = null;
try {
String filePath = System.getProperty("java.io.tmpdir") + "" + fileName;
outputStream = new FileOutputStream(new File(filePath));
outputStream.write(bytes);
outputStream.close();
readExcelFile(filePath);
} catch (Exception ex) {
}
In the above code Iam uploading the file using tomahawk after uploading storing the file in a temporary location.And from there i will be reading using poi.
public static void readExcelFile(String fileName)
{
try{
FileInputStream myInput = new FileInputStream(fileName);
POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
org.apache.poi.ss.usermodel.Workbook workbook = WorkbookFactory.create(myFileSystem);
org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0);
Iterator rowIter = sheet.rowIterator();
for(Row row : sheet) {
//u can read the file contents by iterating.
}
} catch (Exception ex) {
}
}

Flex - how to download a string variable as a file to the local machine?

I have a String variable in my flex (flash builder 4) application containing CSV data. I need to allow the user to download this data to a local file. For example, giving them a "csv" button to click and it might present them with a save file dialog (and I would be sending the contents of my string variable).
Is this possible / how ?
I am using the ResuableFX component for the datagrid to csv. This the code I ended up with that works to save the string to a text file for the user (in a web browser):
var dg2CSV:DataGrid2CSV = new DataGrid2CSV();
dg2CSV.includeHeader=true;
dg2CSV.target=adgEncounters;
var csvText:String=dg2CSV.getCSV();
var MyFile:FileReference = new FileReference();
var csvFileNameDT:String = QuickDateFormatter.format(new Date().toString(),"YYYYMMDDJJNNSS");
MyFile.save(csvText,"Encounters"+csvFileNameDT+".csv");
If you're in an AIR App you can use File.browseForSave().
If you're in a web app, you can use FileReference.save() . The FileReference docs have a lot more info on this.
In many cases, I would recommend using navigateToURL() to open the file outside of Flash and let the browser deal with it.
I'm not sure if there is a way to do this without user interaction.

PDF is plain-text/encoded mess when downloaded from UNC share (using ASP.NET MVC 3 / IE 9)

I have written a controller action that checks for the existence of a PDF file and then returns the file (if found) to the browser as a download.
public ActionResult GetMyFile(string path)
{
if (String.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException("filename"); }
string downloadFileName = System.IO.Path.GetFileName(path);
// The worker process identity must have read access in both the file system and share
// otherwise this always returns false.
if (System.IO.File.Exists(path))
{
FilePathResult result =
File(path, System.Net.Mime.MediaTypeNames.Application.Pdf, downloadFileName);
return result;
}
return Content("no file", "text-plain");
}
Everything works fine, if the path parameter refers to a local path on disk (e.g. "D:\MyFolder\MyFile.pdf"), but when the path is a UNC path, the PDF is returned, but rendered as plain text in the browser.
Here's a snippet of what this looks like...
%PDF-1.3
1 0 obj
<<
/Length 1409
/Filter /FlateDecode
>
stream
X���I�%&/m�{J�J��t��$ؐ#�������iG#)�*��eVe]f#�흼��{����{����;�N'���?\fdl��J�ɞ!���?~|?"~Q�����"�Iw�Ow����:O��,��'?���dg|g/����P��t�Ӄ����:}��Ç������to���}�7��q��/�>O�>�_����9!�g������Y���|�{�p�?�������?����ܿO����s�>���'ڜH������;��D��>�� ���?��?J��t�m����t�C���O�(i�����H������~H��7JLǎ��K�%ͧ������T1�������S���=��.F.#�׷ww�����z�wǟҴ~���x�~���Px�������|3�j����c��)f1��O�1�4�����b�qN̔>������跟j�jB?��݃ ����c��.���ڀ�^ofq�,�Pp���g��=Oo�
��7�}��פ�> ��m)}�~�W!�w��Q�0SR�3���2-���&-��Fhy�S�]���HiyF_���
�4�;Q��l�f��|]>ۍ�hc��C��64���|L�4�9Pξ�{#-�?��|���=1Tl��O�����݂6�����a֡�.fe΀:�����/��1��#�{���������?��|v��}�4�}Cw��!����&z�v��4�����Uj0�&���-��������x�i�ģ����|=�9LnI7�&+�gʃ�;��U� m��
M��.�ޏ�D�QvT��ϯ���f���(��������0��������{_������ui�Rid�6���u��a��x"��m��{�o$����
����.���{#xu�8ӮR�����Ύ�r��{�m��$��O ��v����=�������X!~,E,�P����mf�2%9{��m����֍b���8���ñ��:
�PE��O<�e~jƄ�ߨ���?�Z�������"�Ǟ:����D��N�ߌ����PL��0��U����F4 g�oPW�Ml��#"�~ラ���_�����뾯���?���mGo�������=�bwGr/��b���?t3(�����t��=[\��O+���c������res����u��0�,G��f��̲qO��\�S��7��q̘�܀,.����Wn$��w�M%�����2ymd�I<͑U��eV�A-|�DڵDz�à�/]��J�|�ݾ'��$.\W��R�>���l|%�a�gj���0|{�R�c�������!�lwv?S��^S
E����z��3�����hr�{��R"C�݅o��Ac�*T��Q��IE�6XP5ˮ�j4k��v�
D��-��
endstream
Any thoughts as to why this might be happening?
My environment is an ASP.NET MVC 3 application running in IIS on Windows 7.
The client is Internet Explorer 9 RC running on the same machine.
The UNC path is a shared folder on the same machine as the web server, and is the same physical location used in the "local path test" (which succeeds).
For permissions I have ensured that the worker process identity for my application pool has Read permissions in both the file system and through the share.
I figured it out.
Changing the final return statement from:
return Content("no file", "text-plain");
to
return null;
Seems to have fixed the problem. Although I'm not sure as to why that is. I would think that if the first return (in the if block) was executed, then the final one would have never come into the picture.
I'm happy to accept someone else's answer if they can explain why that is.

Resources