Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Sheriffs:
  • Tim Cooke
  • Knute Snortum
  • Bear Bibeault
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Piet Souris
  • Ganesh Patekar
Bartenders:
  • Frits Walraven
  • Carey Brown
  • Tim Holloway

Where to store files so that it could be served over tomcat

 
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The following code is inside index.html of my application and it works when I access my app via web browser in the following manner(Basically no server involved here):

file:///C:/jack/testing/ui/static/index.html



By works, I mean, I can see the 3 files getting downloaded in csv format with 3KB of size.



Scenario 1:

However, when I have my application (springboot) deployed as WAR file in tomcat of my Eclipse, I access my application in the following manner from the web browser :

http://localhost:8080/testing/index.html



In this scenario, the above javascript code doesn’t completely work. I mean, it downloads the 3 files but the size of the file is 0KB. This makes sense since I am accessing the website over HTTP and my files
should be served by the server.

On windows, how should I modify this line of code return fetch('file:///C:/jack/file/JACK/' + file) so that it starts working in this scenario.

Scenario 2:

Similarly, when I deployed the WAR in the tomcat running on RHEL server, I am accessing my application in the following manner:

https://myserver.com/testing/index/html



In this scenario also, I am noticing empty files are getting downloaded when I used the above code with this change:

return fetch(’/srv/users/JACK’ + file)

What change should I do in the above (RHEL) scenario?

Thanks!
 
Master Rancher
Posts: 451
6
IntelliJ IDE Spring Fedora
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is the javascript that reads those files in the index.html or run from there?

If it's running on a client computer how is javascript that runs on their computer going to download files from the server with a local file system address?
 
Jack Tauson
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Is the javascript that reads those files in the index.html or run from there?



Thanks. Yes, the javascript is inside index.html inside <script></script> tags. It runs from index.html only

If it's running on a client computer how is javascript that runs on their computer going to download files from the server with a local file system address?



The Scenario #1 I mentioned above is not for other users, that's just for my local testing with Eclipse and hence I am trying to figure out how can I access files for my local testing in that case.


Scenario #2 is RHEL server related.

Please let me know if I can answer more questions.
 
Al Hobbs
Master Rancher
Posts: 451
6
IntelliJ IDE Spring Fedora
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't you will be able to read the files using javascript.  There is another thread with a similar topic about read/write using javascript in a web page. For security purposes javascript doesn't have access to the local file system directly.  something like that
 
Jack Tauson
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Al Hobbs wrote:I don't you will be able to read the files using javascript.  There is another thread with a similar topic about read/write using javascript in a web page. For security purposes javascript doesn't have access to the local file system directly.  something like that



Ok. Thanks. How come it's reading the contents of the file when I am accessing the index.html like the following from my web browser as I discussed in my post above.

file:///C:/jack/testing/ui/static/index.html


Also, do you have the link to that discussion thread page that you mentioned? Thanks
 
Al Hobbs
Master Rancher
Posts: 451
6
IntelliJ IDE Spring Fedora
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The thread mentioning it: thread
I'm guessing the reason it works when you run it from a local html file is because the browser can see that the code is local to the computer based on the url or some other way.  When you get the html from a server it can see the url location is not local.
 
Jack Tauson
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Al Hobbs wrote:The thread mentioning it: thread
I'm guessing the reason it works when you run it from a local html file is because the browser can see that the code is local to the computer based on the url or some other way.  When you get the html from a server it can see the url location is not local.



Thanks. Maybe I should move this thread to here :

https://coderanch.com/f/20/HTML-Pages-CSS-JavaScript

Is there a way I could do that or should I post the same question there?
 
Bartender
Posts: 20849
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, JavaScript does have a sandbox, although I've never seen a formal list of its restrictions the way that the ill-fated Java Applet sandbox had.

Some things that applets couldn't do - which are probably also true for JavaScript:

1. Access the client's local filesystem (e.g., erase critical OS files, send a copy of private documents to Bulgaria, implant viruses).

2. Access the client's local printing subsystem (start a print job of 1 billion pages each with a single character on the page)

3. Communicate with servers other than the one that served up the applet. For example, www.botcontroller.com.

It is possible to sign Java applets - and I believe that this is also true of JavaScript - so that these constraints can be relaxed, but the process is tedious and ugly.
 
Jack Tauson
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:Yes, JavaScript does have a sandbox, although I've never seen a formal list of its restrictions the way that the ill-fated Java Applet sandbox had.

Some things that applets couldn't do - which are probably also true for JavaScript:

1. Access the client's local filesystem (e.g., erase critical OS files, send a copy of private documents to Bulgaria, implant viruses).

2. Access the client's local printing subsystem (start a print job of 1 billion pages each with a single character on the page)

3. Communicate with servers other than the one that served up the applet. For example, www.botcontroller.com.

It is possible to sign Java applets - and I believe that this is also true of JavaScript - so that these constraints can be relaxed, but the process is tedious and ugly.



Thanks.

1) I am only trying to access local files system on Windows for testing (in my Scenario #1).

2) On RHEL server, I'm trying to access it from /srv/ directory. Is this also considered as local file system? If not, what could be the reason I am not getting contents of the file but empty csv files?

3) Any alternative to this you would recommend?
 
Tim Holloway
Bartender
Posts: 20849
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The first thing to keep in mind is that a web server is not a file server. Tomcat is a web server. So when you use Tomcat to "serve" a file, it's not actually making that file available to the client as a file, it's making a copy of the data in the server's copy of that file and posting it back to the client as an Http response.

So for a start, you can only return one file per request since the average web client (browser) isn't designed to split an Http response stream into multiple files and store them. In fact, the client won't store the file at all unless the Http content-type indicated matches one of the client's rules that says "store as file" instead of, say "open as Excel spreadsheet".

Secondly, Tomcat isn't actually serving the file, it's serving a resource. In other words, normally when you send an Http request to Tomcat, Tomcat will dissect that URL to determine which webapp will handle the request, and that webapp's WEB-INF/web.xml will contain servlet URL patterns which will be matched against the local part of the URL to see if there's a servlet to send the request to. If instead the URL ends with ".jsp", then Tomcat will look for the servlet whose classname matches that URL pattern, (compiling it if necessary) and turns the request over to the JSP.

If neither of the above suffices, Tomcat has a Default Servlet built in. The Default Servlet gets all the unmatched URL requests for that servlet. It then attempts to translate the local part of the URL into a WAR resource path. If that path resolves to a "directory" (remember that a true WAR is a ZIP file, and has no actual files or directories, just an index and data that convert to files and directories when unzipped), then (assuming the proper settings), Tomcat will create an indexed webpage (HTML) and return it to the client. If instead the resource path resolves to a file (say, /images/birdpics/oriole.jpg), then Tomcat will open that resource (using openResourceAsStream) and copy its contents out as a response like I described above.

Note that all WAR resources are, of necessity part of the WAR itself. And their resource paths reflect that. The root of the WAR's "file system" is the root directory of the WAR. So if you want something more flexible such as a collection of files under /srv. then you have 2 options:

1. Link a WAR resource path to the /srv directory so that it appears that the file in question actually is part of the WAR. Not recommended, since you have to override Tomcat's default, which is not to allow links. Also not recommended, since such a link cannot be defined in a WAR archive, so you'd have to explode the WAR and link manually. And risk erasing the link if you update the webapp.

2. Create a file-copy servlet. This is a better approach, because not only can you read files from any place on the server's filesystem that Tomcat has read-access rights to, but you can also edit those files while copying them or even create "files" from scratch to copy. Since it's a servlet, all that's required is to open the source file, copy/modify/create data as neede and output it to the HttpServletResponse output stream along with the usual headers (Content-Type, Content-Length and so on). If you're minded to, you can even pass in the source directory path via JNDI so that it's not hard-coded into the WAR.
 
Jack Tauson
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Holloway wrote:
Create a file-copy servlet. This is a better approach, because not only can you read files from any place on the server's filesystem that Tomcat has read-access rights to, but you can also edit those files while copying them or even create "files" from scratch to copy. Since it's a servlet, all that's required is to open the source file, copy/modify/create data as neede and output it to the HttpServletResponse output stream along with the usual headers (Content-Type, Content-Length and so on). If you're minded to, you can even pass in the source directory path via JNDI so that it's not hard-coded into the WAR.



Thanks for detailed explanation. Appreciated.

1)Could you tell me by create file-copy servlet, you are referring to something like this?

https://stackoverflow.com/questions/20342457/java-servlet-read-a-file-and-send-it-as-response

2)Also, how Javascript would be interacting with it and getting the file from the server in this scenario.

3)Would this work if the file size is huge? Maybe 500MB or more?
 
Tim Holloway
Bartender
Posts: 20849
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. Pretty much exactly this. Although it can be tweaked to not hard-code the filename being copied.

2. JavaScript isn't needed, although if your client webpage wants to be more dynamic it can request the file via an AJAX URL request.

3. Size limits are mostly limited by server settings and by the client's ability and willingness to store such a file. I don't offhand know if Tomcat has a download size limit. It does have an upload size limit, since otherwise attackers could potentially DDOS or otherwise assault Tomcat.

Also note that you can't do a progress bar on a download when done this way, since the way HTTP works is basically 0........100 DONE! with no intermediate notifications. If that's annoying, there are tools to slice the download into smaller segments and track the segments. jQuery has something like that, I think. Your servlet would be asked for just part of a file (the "seek" function can generally be used to go to the right place), it would return that slice, then the JavaScript client would ask for the next slice, and so forth.
 
Jack Tauson
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the answer. I have few more follow-up questions:

1. Pretty much exactly this. Although it can be tweaked to not hard-code the filename being copied.



Right now my user interface (which consists of Javascript, HTML,CSS) calls REStful webservices(springboot) for user related operations like  getting data etc. For this download thing, user will hit Download button which behind the scenes is going to
get the files to the user from a specific user directory.

In this scenario, should I create a webservice (define an end point in my controller; define doGet method in my DAO interface and have it implemented in the implementation class of DAO interface) along with my other web services?
I am actually, trying to imagine how user (as soon as they hit Download button) would get the file(s) in zip format after they hit Download button.



2. JavaScript isn't needed, although if your client webpage wants to be more dynamic it can request the file via an AJAX URL request.



I am wondering because user is pressing the Download button, Javascript might be needed? And would I need additional libraries lke FileSaver.js that I have used above in my  javascript code?
Sorry, I am little confused here.
 
Marshal
Posts: 24594
55
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jack Tauson wrote:I am wondering because user is pressing the Download button, Javascript might be needed? And would I need additional libraries lke FileSaver.js that I have used above in my  javascript code?
Sorry, I am little confused here.



No, buttons are a feature of HTML which have been there since HTML was first designed. What you're doing on the back end to serve the file has nothing to do with your choice of GUI.
 
Tim Holloway
Bartender
Posts: 20849
125
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, you do not need JavaScript. As I said, HTTP doesn't do file access as such, it just sends copies of the file's content.

If, when you send that content (from your copy servlet), you indicate that you want the content to be saved in a file on the client's filesystem, that's what will happen. Saving is done when you have a content-disposition or content-type header that indicates that the file should be saved. A content-disposition header can include a filename, but that's only a suggestion, since the client will display a file-chooser dialog and let the user determine if/where to save the file. This function is a standard builtin feature in all major web clients, not something you have to write code for - javascript or not.

The filesaver.js libary is primarily intended to save client files that are generated on the client, not downloaded from the server.
 
Jack Tauson
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Tim and Paul for your valuable inputs. One more quick question on which option you guys think is best to follow:

Option #1: Is it a good idea to create this servlet in my spring boot app only. And if I need the same functionality, I should create it separately for other spring boot web app?

OR

Option #2: Should I consider creating it separately, generate a WAR and deploy it with my other spring boot related WARs on Tomcat?

Option #2 sounds better to me because if I have other spring boot web apps wanting to use the same functionality, I could use this separately deployed servlet to download the file from the server. However,  different spring boot webapps might be downloading file from different location so not sure if I could tweak the servlet
to refer to different location on the server or not.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!