I am wokring on spring boot, and i have created a folder web and images floders on this path : myApp/src/web/images
And when doing
private String saveFile(MultipartFile file, String fileName) throws IOException {
byte[] bytes = file.getBytes();
String imagePath = new String(this.servletContext.getRealPath(this.imagesPath) + "/" + fileName);
Path path = Paths.get(imagePath);
Files.write(path, bytes);
return imagePath;
}
i got this error :
java.nio.file.NoSuchFileException: /private/var/folders/4g/wd_lgz8970sfh64zm38lwfhw0000gn/T/tomcat-docbase.8255351399752894174.8098/images/IMG_2018-01-06 15:18:48.486.jpg
where i should put the images folder in order to upload files into it successfully.
Thanks for the help
You could save images into same /myapp/src/web/image/ directory using a fairly straightforward way.
the path in your application start in myapp directory you just need to chain the folow path /usr/web/images and using a FileOutputStream object to save there.
An example below.
private String saveFile(MultipartFile file,String filename) throws IOException{
final String imagePath = "src/web/images/"; //path
FileOutputStream output = new FileOutputStream(imagePath+filename);
output.write(file.getBytes());
return imagePath+filename;
}
Second Edit
if you want to get a image via GET request you can make a method that accept a Request Parameter with the name of the image and produces IMAGE CONTENT TYPE. something like that. (this sample work with a different types of images.)
#RequestMapping(value = "/show/",produces = MediaType.IMAGE_PNG_VALUE)
public #ResponseBody byte[] showImage(#RequestParam("image") String image) throws IOException{
final String imagePath = "src/web/images/";
FileInputStream input = new FileInputStream(imagePath+image);
return IOUtils.toByteArray(input);
}
I'm using apache common dependency to get byte array
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
i am working on spring boot, and i have created a folder web and
images folders on this path : myApp/src/web/images
and this exception :
java.nio.file.NoSuchFileException:
/private/var/folders/4g/wd_lgz8970sfh64zm38lwfhw0000gn/T/tomcat-docbase.8255351399752894174.8098/images/IMG_2018-01-06
15:18:48.486.jpg
At runtime the images folder created in the application source code will not be physically located in an images folder of the folder that hosts the application as this path : myApp/src/web/images is probably not considered by Spring Boot as the application is started.
In Spring Boot, you can access to static resources located in some specific folders such as static or public.
But I am not sure it will help you as you want to not only access to uploded files but also put content in the folder.
So I advise you to use another approach : put the images in a specific folder that is distinct of the application deployment folder.
Besides, generally, you want that the files be available after a shutdown/startup of the application.
So instead of using a relative path to the application to host the images :
myApp/src/web/images
use an absolute path (prefix with /) that is independently of the runtime folder of the application.
Related
I have deployed a spring-boot application JAR file. Now, I want to upload the image from android and store it in the myfolder of resource directory. But unable to get the path of resource directory.
Error is:
java.io.FileNotFoundException: src/main/resources/static/myfolder/myimage.png
(No such file or directory)
This is the code for storing the file in the resource folder
private final String RESOURCE_PATH = "src/main/resources";
String filepath = "/myfolder/";
public String saveFile(byte[] bytes, String filepath, String filename) throws MalformedURLException, IOException {
File file = new File(RESOURCE_PATH + filepath + filename);
OutputStream out = new FileOutputStream(file);
try {
out.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
out.close();
}
return file.getName();
}
UPDATED:
This is what I have tried
private final String RESOURCE_PATH = "config/";
controller class:
String filepath = "myfolder/";
String filename = "newfile.png"
public String saveFile(byte[] bytes, String filepath, String filename) throws MalformedURLException, IOException {
//reading old file
System.out.println(Files.readAllBytes(Paths.get("config","myfolder","oldfile.png"))); //gives noSuchFileException
//writing new file
File file = new File(RESOURCE_PATH + filepath + filename);
OutputStream out = new FileOutputStream(file); //FileNotFoundException
try {
out.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
out.close();
}
return file.getName();
}
Project structure:
+springdemo-0.0.1-application.zip
+config
+myfolder
-oldfile.png
-application.properties
+lib
+springdemo-0.0.1.jar
+start.sh
-springdemo-0.0.1.jar //running this jar file
Usually when you deploy an application (or start it using Java), you start a JAR file. You don't have a resource folder. You can have one and access it, too, but it certainly won't be src/main/resources.
When you build your final artifact (your application), it creates a JAR (or EAR or WAR) file and your resources, which you had in your src/main/resources-folder, are copied over to the output directory and included in the final artifact. That folder simply does not exist when the application is run (assuming you are trying to run it standalone).
During the build process target/ is created and contains the classes, resources, test-resources and the likes (assuming you are building with Maven; it is a little different if you build using Gradle or Ant or by hand).
What you can do is create a folder e.g. docs next to your final artifact, give it the appropriate permissions (chmod/chown) and have your application output files into that folder. This folder is then expected to exist on the target machine running your artifact, too, so if it doesn't, it would mean the folder does not exist or the application lacks the proper permissions to read from / write to that folder.
If you need more details, don't hesitate to ask.
Update:
To access a resource, which is bundled and hence inside your artifact (e.g. final.jar), you should be able to retrieve it by using e.g. the following:
testText = new String(ControllerClass.class.getResourceAsStream("/test.txt").readAllBytes());
This is assuming your test.txt file is right under src/main/resources and was bundled to be directly in the root of your JAR-file (or target folder where your application is run from). ControllerClass is the controller, which is accessing the file. readAllBytes just does exactly this: read all the bytes from a text file. For accessing images inside your artifact, you might want to use ImageIO.
IF you however want to access an external file, which is not bundled and hence not inside your artifact, you may use File image = new File(...) where ... would be something like "docs/image.png". This would require you to create a folder called docs next to your JAR-artifact and put a file image.png inside of it.
You of course also may work with streams and there are various helpful libraries for working with input- and output streams.
The following was meant for AWT, but it works in case you really want to access the bytes of your image: ImageIO. In a controller you usually wouldn't want to do that, but rather have your users access (and thus download) it from a given available folder.
I hope this helps :).
I am trying to use file, when running application as JAR.
When I run application through Intelij, everything is fine. However when I try to run it via jar, I cannot access the file.
I tried to read few topics containing similar matter, but non of them help
(like Reading a resource file from within jar or How do I read a resource file from a Java jar file?
)
Here is my target tree, and resources:
When I use
String path = String
.join("", "classpath:static\assets\config\", fileName);
File file = ResourceUtils.getFile(path);
InputStream targetStream = new FileInputStream(file)
During intelij run, everything works.
In the case of jar, I tried:
String path = String
.join("", "static\assets\config\", fileName).replace("\\","/")).toExternalForm();
String path2 = String
.join("", "static\assets\config\", fileName).replace("\\","/")).getFile();
String path3 = String
.join("", "static\assets\config\", fileName).replace("\\","/")).getPath();
and many other. They result in correct path, for example:
file:/D:/Projects/myProject/target/classes/static/assets/config/fileName (in case of toExternalForm)
/D:/Projects/myProject/target/classes/static/assets/config/fileName (in case of getFile)
However all of them results in null InputStream, when I try:
InputStream in = getClass().getResourceAsStream(everyPath);
I get an error:
java.io.FileNotFoundException: D:\Projects\myProject\target\project-app-1.0.jar\BOOT-INF\classes\static\assets\config\fileName (The system cannot find the path specified)
When the path in the project-app-1.0.jar when I open it by 7zip is exactly:
D:\Projects\myProject\target\project-app-1.0.jar\BOOT-INF\classes\static\assets\config\fileName
This is how my resource handler looks like:
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/resources/", "classpath:/static/"};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}
forget about "files" when you want to use something inside your jar, its just a simple "Resource" that your have to use with getResource.
If you use a standard packaging system, everything inside "resources" folder are put at the root of your JAR, so if you want to read your "foo.txt" file inside "static\assets\config\" folder you have to do use method:
InputStream in = ClassLoader.getSystemResourceAsStream("static/assets/config/foo.txt");
I have a Java web application running on Tomcat. I want to load static images that will be shown both on the Web UI and in PDF files generated by the application. Also new images will be added and saved by uploading via the Web UI.
It's not a problem to do this by having the static data stored within the web container but storing and loading them from outside the web container is giving me headache.
I'd prefer not to use a separate web server like Apache for serving the static data at this point. I also don't like the idea of storing the images in binary in a database.
I've seen some suggestions like having the image directory being a symbolic link pointing to a directory outside the web container, but will this approach work both on Windows and *nix environments?
Some suggest writing a filter or a servlet for handling the image serving but those suggestions have been very vague and high-level without pointers to more detailed information on how to accomplish this.
I've seen some suggestions like having the image directory being a symbolic link pointing to a directory outside the web container, but will this approach work both on Windows and *nix environments?
If you adhere the *nix filesystem path rules (i.e. you use exclusively forward slashes as in /path/to/files), then it will work on Windows as well without the need to fiddle around with ugly File.separator string-concatenations. It would however only be scanned on the same working disk as from where this command is been invoked. So if Tomcat is for example installed on C: then the /path/to/files would actually point to C:\path\to\files.
If the files are all located outside the webapp, and you want to have Tomcat's DefaultServlet to handle them, then all you basically need to do in Tomcat is to add the following Context element to /conf/server.xml inside <Host> tag:
<Context docBase="/path/to/files" path="/files" />
This way they'll be accessible through http://example.com/files/.... For Tomcat-based servers such as JBoss EAP 6.x or older, the approach is basically the same, see also here. GlassFish/Payara configuration example can be found here and WildFly configuration example can be found here.
If you want to have control over reading/writing files yourself, then you need to create a Servlet for this which basically just gets an InputStream of the file in flavor of for example FileInputStream and writes it to the OutputStream of the HttpServletResponse.
On the response, you should set the Content-Type header so that the client knows which application to associate with the provided file. And, you should set the Content-Length header so that the client can calculate the download progress, otherwise it will be unknown. And, you should set the Content-Disposition header to attachment if you want a Save As dialog, otherwise the client will attempt to display it inline. Finally just write the file content to the response output stream.
Here's a basic example of such a servlet:
#WebServlet("/files/*")
public class FileServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
When mapped on an url-pattern of for example /files/*, then you can call it by http://example.com/files/image.png. This way you can have more control over the requests than the DefaultServlet does, such as providing a default image (i.e. if (!file.exists()) file = new File("/path/to/files", "404.gif") or so). Also using the request.getPathInfo() is preferred above request.getParameter() because it is more SEO friendly and otherwise IE won't pick the correct filename during Save As.
You can reuse the same logic for serving files from database. Simply replace new FileInputStream() by ResultSet#getInputStream().
See also:
Recommended way to save uploaded files in a servlet application
Abstract template for a static resource servlet (supporting HTTP cache)
How to retrieve and display images from a database in a JSP page?
How to stream audio/video files such as MP3, MP4, AVI, etc using a Servlet
You can do it by putting your images on a fixed path (for example: /var/images, or c:\images), add a setting in your application settings (represented in my example by the Settings.class), and load them like that, in a HttpServlet of yours:
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
FileInputStream fis = new FileInputStream(filename);
int b = 0;
while ((b = fis.read()) != -1) {
response.getOutputStream().write(b);
}
Or if you want to manipulate the image:
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
File imageFile = new File(filename);
BufferedImage image = ImageIO.read(imageFile);
ImageIO.write(image, "image/png", response.getOutputStream());
then the html code would be <img src="imageServlet?imageName=myimage.png" />
Of course you should think of serving different content types - "image/jpeg", for example based on the file extension. Also you should provide some caching.
In addition you could use this servlet for quality rescaling of your images, by providing width and height parameters as arguments, and using image.getScaledInstance(w, h, Image.SCALE_SMOOTH), considering performance, of course.
Requirement : Accessing the static Resources (images/videos., etc.,) from outside of WEBROOT directory or from local disk
Step 1 :
Create a folder under webapps of tomcat server., let us say the folder name is myproj
Step 2 : Under myproj create a WEB-INF folder under this create a simple web.xml
code under web.xml
<web-app>
</web-app>
Directory Structure for the above two steps
c:\programfile\apachesoftwarefoundation\tomcat\...\webapps
|
|---myproj
| |
| |---WEB-INF
| |
|---web.xml
Step 3:
Now create a xml file with name myproj.xml under the following location
c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost
CODE in myproj.xml:
<Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" />
Step 4:
4 A) Now create a folder with name myproj in E drive of your hard disk and create a new
folder with name images and place some images in images folder (e:myproj\images\)
Let us suppose myfoto.jpg is placed under e:\myproj\images\myfoto.jpg
4 B) Now create a folder with name WEB-INF in e:\myproj\WEB-INF and create a web.xml in WEB-INF folder
Code in web.xml
<web-app>
</web-app>
Step 5: Now create a .html document with name index.html and place under e:\myproj
CODE under index.html
Welcome to Myproj
The Directory Structure for the above Step 4 and Step 5 is as follows
E:\myproj
|--index.html
|
|--images
| |----myfoto.jpg
|
|--WEB-INF
| |--web.xml
Step 6: Now start the apache tomcat server
Step 7: open the browser and type the url as follows
http://localhost:8080/myproj
then u display the content which is provided in index.html
Step 8: To Access the Images under your local hard disk (outside of webroot)
http://localhost:8080/myproj/images/myfoto.jpg
Add to server.xml :
<Context docBase="c:/dirtoshare" path="/dir" />
Enable dir file listing parameter in web.xml :
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
This is story from my workplace:
- We try to upload multiply images and document files use Struts 1 and Tomcat 7.x.
- We try to write uploaded files to file system, filename and full path to database records.
- We try to separate file folders outside web app directory. (*)
The below solution is pretty simple, effective for requirement (*):
In file META-INF/context.xml file with the following content:
(Example, my application run at http://localhost:8080/ABC, my application / project named ABC).
(this is also full content of file context.xml)
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ABC" aliases="/images=D:\images,/docs=D:\docs"/>
(works with Tomcat version 7 or later)
Result: We have been created 2 alias. For example, we save images at: D:\images\foo.jpg
and view from link or using image tag:
<img src="http://localhost:8080/ABC/images/foo.jsp" alt="Foo" height="142" width="142">
or
<img src="/images/foo.jsp" alt="Foo" height="142" width="142">
(I use Netbeans 7.x, Netbeans seem auto create file WEB-INF\context.xml)
If you decide to dispatch to FileServlet then you will also need allowLinking="true" in context.xml in order to allow FileServlet to traverse the symlinks.
See http://tomcat.apache.org/tomcat-6.0-doc/config/context.html
If you want to work with JAX-RS (e.g. RESTEasy) try this:
#Path("/pic")
public Response get(#QueryParam("url") final String url) {
String picUrl = URLDecoder.decode(url, "UTF-8");
return Response.ok(sendPicAsStream(picUrl))
.header(HttpHeaders.CONTENT_TYPE, "image/jpg")
.build();
}
private StreamingOutput sendPicAsStream(String picUrl) {
return output -> {
try (InputStream is = (new URL(picUrl)).openStream()) {
ByteStreams.copy(is, output);
}
};
}
using javax.ws.rs.core.Response and com.google.common.io.ByteStreams
if anyone not able to resolve his problem with accepted answer, then note these below considerations:
no need to mention localhost:<port> with <img> src attribute.
make sure you are running this project outside eclipse, because eclipse creates context docBase entry on its own inside its local server.xml file.
Read the InputStream of a file and write it to ServletOutputStream for sending binary data to the client.
Local file You can read a file directly using FileInputStream('path/image.png').
Mongo DataBase file's you can get InputStream using GridFS.
#WebServlet("/files/URLStream")
public class URLStream extends HttpServlet {
private static final long serialVersionUID = 1L;
public URLStream() {
super();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
File source = new File("D:\\SVN_Commit.PNG");
long start = System.nanoTime();
InputStream image = new FileInputStream(source);
/*String fileID = request.getParameter("id");
System.out.println("Requested File ID : "+fileID);
// Mongo DB GridFS - https://stackoverflow.com/a/33544285/5081877
image = outputImageFile.getInputStream();*/
if( image != null ) {
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
ServletOutputStream sos = response.getOutputStream();
try {
bin = new BufferedInputStream( image );
bout = new BufferedOutputStream( sos );
int ch =0; ;
while((ch=bin.read())!=-1) {
bout.write(ch);
}
} finally {
bin.close();
image.close();
bout.close();
sos.close();
}
} else {
PrintWriter writer = response.getWriter();
writer.append("Something went wrong with your request.");
System.out.println("Image not available.");
}
System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start));
}
}
Result the URL directly to the src attibute.
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream?id=5a575be200c117cc2500003b' alt="mongodb File"/>
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream' alt="local file"/>
<video controls="controls" src="http://172.0.0.1:8080/ServletApp/files/URLStream"></video>
I did it even simpler. Problem: A CSS file had url links to img folder. Gets 404.
I looked at url, http://tomcatfolder:port/img/blablah.png, which does not exist. But, that is really pointing to the ROOT app in Tomcat.
So I just copied the img folder from my webapp into that ROOT app. Works!
Not recommended for production, of course, but this is for an internal tool dev app.
After using images for example on a Button, when I build the application creating the .jar file and execute only the file, the images are not there but would only show if I copy the images folder in the same directory as the jar file. Why is that and how can I resolve this if possible?
I am currently using the following code to set the icon/image:
JButton btn = new JButton("Text", "img/icon.png");
The fact that you can use the images when they are stored outside the jar, suggests that you are doing something of the kind:
File image = new File("directory/image.jpg");
InputStream is = new FileInputStream(image);
This reads a file from a directory on the file system, not from the classpath. Now, if you have packaged your image in a "directory" inside your Jar, you must load the image from the classpath.
InputStream is = getClass().getResourceAsStream("/directory/image.jpg");
(note the slash in the path)
Or
InputStream is = getClass().getClassLoader().getResourceAsStream("directory/image.jpg");
(note the absence of the slash in the path)
Your example, as it is now, should not compile. (The second argument of your JButton construtor is an Icon, not a String, java 8). So when you were getting the image from the file system, you were probably doing something else.
With your example, you need to read an image from the inputstream and convert it to an Icon:
try (InputStream is = getClass.getClassLoader().getResourcesAsStream("directory/image.jpg")) {
BufferedImage image = ImageIO.read(is);
return new JButton("Text", new ImageIcon(image));
} catch (IOException exc) {
throw new RuntimeException(exc);
}
That should use the image that is located in "directory" inside your jar. Of course, you need to include the image within your jar, or you will get a NullPointerException on the inputstream is.
I think you need to understand the
ClassLoader:
A typical strategy is to transform the name into a file name and then
read a "class file" of that name from a file system.
So with this you will be able to lead Resources of your project with getResource
public URL getResource(String name)
Finds the resource with the given name. A resource is some data
(images, audio, text, etc) that can be accessed by class code in a way
that is independent of the location of the code.
Using Tomcat and Struts 2.
public FileAction class
{
......
public upload()
{
.....
String fullFileName = request.getContextPath() + "/productImages/" + filename;
File theFile = new File(fullFileName);
FileUtils.copyFile(upload, theFile);
.....
}
}
The problem is when I upload an image it will not add image in localhost:8085/shoppingCart/productImages and also not give any exception.
But when i write String fullFileName="c:upload/productImages/" + filename; it will save the file at c:upload/productImages/ path
mean working normal in c:upload/productImages/ case
If you want the file uploaded to the server's context, you need to use ServletContext.getRealPath(...) to find the base directory of the deployed application. Note that this will not work if you're deploying a war file. Uploaded files should go to an absolute location on the server itself.
For downloading an uploaded image you'd write a stream result (since you're using Struts 2) and use it to load and stream the uploaded file back to the client.