How I save and retrieve an image on my server in a java webapp
instead of writing it to my C drive I'm going to run it on the server, but where should I store the image to later retriev and display in an xhtml file?
That depends on how much control you have over configuring the server. Ideal would be to configure a fixed path outside the Tomcat webapps folder. For example, /var/webapp/upload
. You can set this path as a VM argument or environment variable so that your webapp can retrieve it programmatically without the need to change the code.
For example, when specifying as VM argument -Dupload.location=/var/webapp/upload
, you can complete the upload as follows:
Path folder = Paths.get(System.getProperty("upload.location"));
String filename = FilenameUtils.getBaseName(uploadedFile.getName());
String extension = FilenameUtils.getExtension(uploadedFile.getName());
Path file = Files.createTempFile(folder, filename + "-", "." + extension);
try (InputStream input = uploadedFile.getInputStream()) {
Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);
}
String uploadedFileName = file.getFileName().toString();
// Now store it in DB.
As to serving the file back, most ideal would be to add the upload location as a separate <Context>
to Tomcat. E.g.
<Context docBase="/var/webapp/upload" path="/uploads" />
This way you can access it directly by http://example.com/uploads/foo-123456.ext
If you have zero control over configuring the server, then, well, storing in the DB or sending to a 3rd party host such as Amazon S3 is your best bet.
See also:
- How to provide relative path in File class to upload any file?
- Reliable data serving
Saving and serving images in a Java Web app
Question 1:
1.1 : is a good approach, it should only be revised
1.2 : if you like to user home directory you should use System.getProperty("user.home") instead of System.getProperty("user.dir")
Normally, while the launch of the application you should create a temporary folder myapplicationimp" on user.home directory in which you manage the images.
EX : you can use @PostConstruct if you use springframework that check and create the folder instantly after bean creation (still an example).
Question 2:
In production save data we use the same aproache that you used, or a third-party environnement to like distant repositories (as google drive) or databases.
hope this will help
How to save and load an image on a Tomcat server
You should not write images retrieved dynamically into your webapp's folder - this opens you up for a whole category of problems. Instead, save them to a folder outside of the appserver's root directory and create a download servlet that will serve these resources.
The danger otherwise is that you'll retrieve some jsp file from external sources, save them to your appserver and on download the appserver will happily execute it server side.
Assume your webapp's directory to be non-writeable to your webapp. This will also ease backup and updates: Imagine you'll need to install an update or migrate to a different server: The application you have on your server will only partially be contained in its *.war file. If there's an explicit resource directory, you can back this up independently (or put it on a network share drive)
Save image files in web application, java
Go to this repository and go to the display-image-from-db
branch. The basic approach is the following:
In the entity you have:
@Lob
private Byte[] image;ImageController.java
- you get the image via aMultipartFile
@PostMapping("recipe/{id}/image")
public String handleImagePost(@PathVariable String id, @RequestParam("imagefile") MultipartFile file){
imageService.saveImageFile(Long.valueOf(id), file);
return "redirect:/recipe/" + id + "/show";
}Call the
imageService
to save the image passing thefile
as an argument.The service basically copies the image content to a byte array, and finally you assign this byte array to your entity.
@Override
@Transactional
public void saveImageFile(Long recipeId, MultipartFile file) {
try {
Recipe recipe = recipeRepository.findById(recipeId).get();
Byte[] byteObjects = new Byte[file.getBytes().length];
int i = 0;
for (byte b : file.getBytes()){
byteObjects[i++] = b;
}
recipe.setImage(byteObjects);
recipeRepository.save(recipe);
} catch (IOException e) {
//todo handle better
log.error("Error occurred", e);
e.printStackTrace();
}
}
For the full source code go to the repo, that will definitely help.
However I strongly suggest storing the files on the disk and not in the DB. The DB should only store the path to the files. For such solution here is an example: link
TL;DR
- I would strongly suggest not storing the data in the database itself but on the filesystem. (E.g.: In a folder.)
- This guide might be also helpful.
- Here you find a complete RESTful implementation.
Cheers!
How can I retrieve an image from a folder using a JavaEE application running in Tomcat server?
HttpServlet will works perfect for your needs. You can define more servlets if needed.
use:
youraddress.xxx/images/filename.png
this is important
@WebServlet("/images/*")
It will automatically leads to folder defined in PATH and retrieve the image based on the name.
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
@WebServlet("/images/*")
public class ImageServlet extends HttpServlet {
public static final String PATH = "C:/"
/*
linux
public static final String PATH = "/home/images/"
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filename = request.getPathInfo().substring(1);
File file = new File(PATH,filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length",String.valueOf(file.length()));
response.setHeader("Content-Disposition","inline; filename=\""+filename +"\"");
Files.copy(file.toPath(),response.getOutputStream());
}
}
how to download image from any web page in java
try (URL url = new URL("http://www.yahoo.com/image_to_read.jpg")) {
Image image = ImageIO.read(url);
} catch (IOException e) {
// handle IOException
}
See javax.imageio
package for more info. That's using the AWT image. Otherwise you could do:
URL url = new URL("http://www.yahoo.com/image_to_read.jpg");
InputStream in = new BufferedInputStream(url.openStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while (-1!=(n=in.read(buf)))
{
out.write(buf, 0, n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
And you may then want to save the image so do:
FileOutputStream fos = new FileOutputStream("C://borrowed_image.jpg");
fos.write(response);
fos.close();
Related Topics
How to Enable Commit on Focuslost for Tableview/Treetableview
How to Serialize a List in Java
When to Use Atomicreference in Java
When Should We Use a Preparedstatement Instead of a Statement
How to Pass a Variable from One Thread Group to Another in Jmeter
If I Synchronized Two Methods on the Same Class, Can They Run Simultaneously
How to Make Line Animation Smoother
Compare Two Objects in Java with Possible Null Values
Should I Use Java.Util.Date or Switch to Java.Time.Localdate
How to Execute Windows Commands Using Java - Change Network Settings
Lambda Expression and Method Overloading Doubts
Jaxb Marshalling Unmarshalling with Cdata
Is This the Best Way to Rewrite the Content of a File in Java