I have Java Web Application using Spring Boot, I want to display in JSP page ,images which are in an extern folder (E:/images) in file system.
I looked too many pages in google,I found on stackoverflow a post that say I should write a servlet to get the image : am I missing something or should I do it with an other way , please give me more details I m kind of new to Spring. thanks for your help.
in my Controller :
#RequestMapping(value="/images",method = RequestMethod.GET)
public #ResponseBody void affichimage(#RequestParam("id") Integer Iddd,HttpServletResponse response,HttpServletRequest request) throws IOException
{
Annonce annonce=new Annonce();
annonce=annoncedao.findOne(Iddd); // get the right annonce from
//database
File imageFile = new File(annonce.getimage()); // in image I have
//the link to images ex : E:/images/image1.jpeg
response.setContentType("image/jpeg");
BufferedImage image = ImageIO.read(imageFile);
ImageIO.write(image, "image/jpeg", response.getOutputStream());
}
in JSP :
< img class="imagesaffichage" src="/images?id=${annonce.id}" alt="No image"/>
I also added this to my application :
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("file:///E:/images/");
}
I found the solution , I had to change the above method :
#RequestMapping(value="/images",method = RequestMethod.GET)
public #ResponseBody void affichimage(#RequestParam("id") Integer
Iddd,HttpServletResponse response,HttpServletRequest request) throws
IOException,NullPointerException
{
Annonce annonce=new Annonce();
annonce=annoncedao.findOne(Iddd); // get the right annonce from
//database
File imageFile = new File(img);
response.setContentType("image/jpeg");
InputStream in=new FileInputStream(imageFile);
IOUtils.copy(in, response.getOutputStream());
}
Related
I have a folder structure /data/reports on a file system, which contains all reports.
How can I configure a SpringBoot application to serve the contents of this file sytem.
Currently I have tried few options, but none working
#Configuration
#EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
#Value(value = "${spring.resources.static-locations:#{null}}")
private String fileSystem;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/data/reports/**")
.addResourceLocations(fileSystem)
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
}
and in application.properties I have defined
spring.resources.static-locations=file:///data/reports
server.servlet.jsp.init-parameters.listings=true
But in both cases, when I try
http://host:port/application/data/reports
I'm getting 404
What am I missing ?
Based on the suggestions given, I realized that one mistake I'm doing is to access the reports via
http://host:port/application/data/reports
instead of
http://host:port/data/reports
if I use application in the request, those calls will go through RequestDispatcher and will try to find for a matching RequestMapping, which does not exist. I think I'm convinced so far.
But the problem I'm seeing now is, I'm getting SocketTimeoutException while trying to read from the resource listed in the URL. I had put some breakpoints in Spring source "ResourceHttpMessageConverter.java"
protected void writeContent(Resource resource, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
try {
InputStream in = resource.getInputStream(); //It is timing out here
try {
StreamUtils.copy(in, outputMessage.getBody());
}
catch (NullPointerException ex) {
// ignore, see SPR-13620
}
The resource is a small text file with 1 line "Hello World". Yet it is timing out.
The resource in the above class is a FileUrlResource opened on file:///c:/data/reports/sample.txt
On the other hand, I tried to read that resource as
File file = new File("c:/data/reports/sample.txt");
System.out.println(file.exists());
URL url = file.toURI().toURL();
URLConnection con = url.openConnection();
InputStream is = con.getInputStream(); //This works
Thanks
I am new in Spring-Boot...
I want to upload images or videos, and store them in a persistant folder "upload-storage" in the class-path of my project in the server. I don't want to store them in the database (20 Mo).
Spring-Boot store them in target/upload-storage.
That functions : I can show the videos on the view with the controller and Thymeleaf. I can close tomcat, close the browser, and open them again : that functions.
But the day after, upload-storage is disapeared !
I think that I don't use the good process.
But I found how to upload an image : ok. I found how to show images from a folder in class-path : ok. I found how to upload images to database. But nothing to store the uploaded images in a persistant folder.
Can you help me ? Can you tell me the good process ?
Some details :
I have an entity "video" to store name, extension, length,... of the video.
I have "VideoRepository" and "VideoService" to manage the requests with "Video".
I have a "StorageService" and "StorageServiceImpl" to manage the upload of video and images : It as to upload the video and save it in a folder called "upload-storage" : I will come back on it farther.
I have a videoForm.html first with a form to select a file and send it to "UploadController", then an other form to show the video, the datas extracted from the video, modify the name or add precisions, and send this form to a "VideoController" who save the entity.
A part of the code of "UploadController" :
`
#Controller
public class UploadController extends BaseController {
private final StorageService storageServiceImpl;
#Autowired
public UploadController(StorageService storageServiceImpl) {
this.storageServiceImpl = storageServiceImpl;
}
#PostMapping("/upload")
public String recupereUpload(#RequestParam("file") MultipartFile file,Model model){
String filename ="";
try {
final long limit = 200 * 1024 * 1024;
if (file.getSize() > limit) {
model.addAttribute("message", "Taille du fichier trop grand (>200MB)");
model.addAttribute("ok", false );
}
filename = storageServiceImpl.store(file);
model.addAttribute("filename", filename);
model.addAttribute("message", "Le téléchargement de " + filename+" est réussi !");
} catch (Exception e) {
model.addAttribute("message", "FAIL to upload " + filename + "!");
model.addAttribute("ok", false );
}
Video video = new Video();
model.addAttribute("ok", true );
model.addAttribute("video", video);
String baseName = storageServiceImpl.getBaseName(filename);
String ext = storageServiceImpl.getExtension(filename);
model.addAttribute("nom", baseName);
model.addAttribute("ext", ext);
model.addAttribute("nomorigin", filename);
model.addAttribute("size", Math.round(file.getSize()/1024));
String typExt = storageServiceImpl.getType(ext);
model.addAttribute("typExt", typExt);
return "elementVideo/videoForm";
}
`
"StorageServiceImpl" has different methods :
getExtension(String filename){...}
getType(String ext){...}
getType(String ext){...}
getBaseName(String filename){...}
The main method is store(MultipartFile file) {...} :
#Service
public class StorageServiceImpl implements StorageService {
private final Path storageLocation = Paths.get("upload-storage");
#Override
public String store(MultipartFile file) {
try {
// Vérification de l'existence :
if (file.isEmpty()) {
throw new Exception("Failed to store empty file " + file.getOriginalFilename() );
}
// Vérification de la nature et traitement du fichier uploadé :
String ext = getExtension(file.getOriginalFilename());
String[] extAutorise = {"mp4", "avi","ogg","ogv","jpg","jpeg","png","gif"};
String fileNameTarget ="";
if ( ArrayUtils.contains( extAutorise, ext)) {
//Définir le fichier destination :
fileNameTarget = file.getOriginalFilename();
fileNameTarget = fileNameTarget.replaceAll(" ", "_");
File dir = storageLocation.toFile();
String serverFile = dir.getAbsolutePath() + File.separator + fileNameTarget ;
try {
try (InputStream is = file.getInputStream();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile))
) {
int i;
while ((i = is.read()) != -1) {
stream.write(i);
}
stream.flush();
}
} catch (IOException e) {
System.out.println("error : " + e.getMessage());
}
}
return fileNameTarget;
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
}
`
With this code, a folder "upload-storage" is created at the root of the project.
The video is uploaded in this folder...
But in "videoForm.html", the code
<video id="video" th:src="'/upload-storage/'+${filename}" height="60"
autoplay="autoplay"></video>
shows nothing.
I have an other solution.
In StorageServiceImpl, I use the code :
private final String storageLocation = this.getClass().getResource("/static/").getPath();
at place of :
private final Path storageLocation = Paths.get("upload-storage");
then :
File dir = new File(storageLocation + File.separator + "upload-storage");
at place of :
File dir = storageLocation.toFile();
then :
File serverFile = new File(dir.getAbsolutePath() + File.separator + fileNameTarget);
at place of :
String serverFile = dir.getAbsolutePath() + File.separator + fileNameTarget ;
With this solution, upload-storage is created in target folder.
I use an other controller BaseController :
public class BaseController {
public static final String PARAM_BASE_URL = "baseURL";
public String getBaseURL(HttpServletRequest request){
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
}
}
`
UploadController extends this BaseController.
I add HttpServletRequest request in recupereUpload() :
#PostMapping("/upload")
public String recupereUpload(#RequestParam("file") MultipartFile file,
Model model, HttpServletRequest request ){
I add in the model sent by recupereUpload :
model.addAttribute(PARAM_BASE_URL, getBaseURL(request));
And at last, I can see my video in videoForm.html with the code :
<video id="video" th:src="${baseURL}+'/upload-storage/'+${filename}" height="60" autoplay="autoplay"></video>
I can close Tomcat, close Eclipse, close the machine, and open all again : all is preserved and I can see the video.
But some time later : all is disappeared.
There must be a better solution.
Can you help me ?
Why dont you use Spring Content for the video content portion of your solution? That way you won't need to implement any of the video content handling. Spring Content will provide this for you. To add Spring Content to your project:
Add Spring Content to your classpath.
pom.xml
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>0.0.10</version>
</dependency>
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>content-fs-spring-boot-starter</artifactId>
<version>0.0.10</version>
</dependency>
Associate content with your Video entity.
Video.java
#Entity
public class Video {
...
#ContentId
private String contentId;
#ContentLength
private Long contetLen;
#MimeType
private String mimeType;
...
Set up a "persistent folder" as the root of your video store. This is where uploaded videos will be stored/streamed from. Also create a VideoStore interface to describe to SC how you want to associate your content.
SpringBootApplication.java
#SpringBootApplication
public class YourSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(YourSpringBootApplication.class, args);
}
#Configuration
#EnableFilesystemStores
public static class StoreConfig {
File filesystemRoot() {
return new File("/path/to/your/videos");
}
#Bean
public FileSystemResourceLoader fsResourceLoader() throws Exception {
return new FileSystemResourceLoader(filesystemRoot().getAbsolutePath());
}
}
#StoreRestResource(path="videos")
public interface VideoStore extends ContentStore<Video,String> {
//
}
}
This is all you need to create a REST-based video service at /videos. Essentially, when your application starts, Spring Content will look at your dependencies (seeing Spring Content FS/REST), look at your VideoStore interface and inject an implementation of that interface based on the filesystem. It will also inject a controller that forwards http requests to that implementation as well. This saves you having to implement any of this yourself.
So...
POST /videos/{video-entity-id}
with a multipart/form-data request will store the video in /path/to/your/videos and associate it with the video entity whose id is video-entity-id.
GET /videos/{video-entity-id}
will fetch it again. This supports partial content requests or byte ranges; i.e. video streaming too.
and so on...support full CRUD.
There are a couple of getting started guides here. The reference guide is here. And there is a tutorial video here. The coding bit starts about 1/2 way through.
HTH
Did you enable the upload by adding the following property in the application.properties file?
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
I have written an article about how to upload a multipart file in spring boot using thymeleaf. Here is the service used for the upload.
package com.uploadMultipartfile.storage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
#Service
public class FileSystemStorageService implements StorageService
{
private final Path rootLocation;
#Autowired
public FileSystemStorageService(StorageProperties properties) {
this.rootLocation = Paths.get(properties.getUploadDir()).toAbsolutePath().normalize();
try {
Files.createDirectories(this.rootLocation);
} catch (Exception ex) {
throw new StorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
#Override
public String store(MultipartFile file)
{
// Normalize file name
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try
{
if (file.isEmpty())
{
throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
}
// Copy file to the target location (Replacing existing file with the same name)
Path targetLocation = this.rootLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return fileName;
}
catch (IOException e)
{
throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
}
}
#Override
public void init()
{
try
{
Files.createDirectory(rootLocation);
}
catch (IOException e)
{
throw new StorageException("Could not initialize storage", e);
}
}
}
Here is a link to get the code of the application. http://mkaroune.e-monsite.com/pages/spring/spring-boot-multipart-file-upload.html
I can download data via HttpUrlConnection and InputStream but I need to download raw-data. So, i want to create a DownloadManager via raw-data, then using raw-data I convert this data to binary or image format. According to my research, I see "download file from url" but I can't download file in mac? Always, I get FileNotFoundException. Please help me. How I can download data from url?
public class DownloadData extends AsyncTask<Void,Void,Void> {
#Override
protected Void doInBackground(Void... params) {
try {
downloadData("https://blablalabla/get");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public void downloadData(String myurl) throws IOException {
URL u = new URL(myurl);
InputStream is = u.openStream();
DataInputStream dis = new DataInputStream(is);
byte[] buffer = new byte[1024];
int length;
OutputStream fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/Users/ilknurpc/Desktop/text.docx"));
while ((length = dis.read(buffer))>0) {
fos.write(buffer, 0, length);
}
}
}
If you want to construct a workable download manager, I would suggest that you take a look at the
Tomcat Default Servlet Implementation
.
There a few number of HTTP headers that you need to understand such as E-Tags and Http Range Headers for a proper implementation.
Thankfully the Tomcat Default Servlet handles the prerequisites for you.
You can adapt this servlet in your code with minor changes (package declaration etc).
I have a problem of downloading my uploaded files from amazon s3 service. I have succesfully implemented the upload section, all I need is to download these file to my local hardrive the view them later. My application is a spring mvc application.
This is my controller to call the download service
#Controller
public class fileController{
#Autowired S3Service s3Service;
#Autowired AwsConfig awsConfig;
#Autowired Environment env;
#Autowired DocRepository docRepo;
#RequestMapping(value="downloadDocume")
public void downloadDocument(#RequestParam("docId") Long docId
,HttpServletRequest request ,HttpServletResponse response)){
Document doc = docRepo.findOne(docId);
String docName = doc.getAsset().getName();
String ASSET_PATH = awsConfig.getBaseUrl()+"/"+
awsConfig.getBucket()+"/";
if (Objects.equals(env.getProperty("spring.profiles.active"),"prod")){
ASSET_PATH= awsConfig.getBaseUrl()+"/"+
awsConfig.getBucket()+"/";
}
String filtered = StringUtils.delete(docName, ASSET_PATH);
String mimetype = request.getSession().getServletContext().getMimeType(filtered);
FileStream file = s3Service.getAssetByName("/Documents/", filtered);
response.setContentType(mimetype);
response.setContentLength((int) file.getSize());
response.setHeader("Content-Disposition","attachment; filename=\"" + docName +"\"");
FileCopyUtils.copy(file.getInputStream(), response.getOutputStream());
}
}
//This is my S3Sservice class with the download method
#Service
public class S3Service{
public FileStream getAssetByName(String path , String name)
throws FileNotFoundException{
AmazonS3Client s3 = new AmazonS3Client(
new BasicAWSCredentials(awsConfig.getAccessKey(), awsConfig.getSecretKey()));
s3.setEndpoint(awsConfig.getBaseUrl());
s3.setS3ClientOptions(new S3ClientOptions().withPathStyleAccess(true));
S3Object obj = s3.getObject(new GetObjectRequest(awsConfig.getBucket(), getS3Path(path) + name));
return new FileStream(obj.getObjectContent(), obj.getObjectMetadata().getContentLength());
}
}
Wow.. The solution was very simple.. I just used the the html download link and passed the parameters on my jsp like this. This is i my document.jsp
<a class="btn btn-primary" href="${document.asset.name}" download="${document.asset.name}">Download Document</a>
I change my downloadDocument() in my controller to look like this
public void downloadDocument(#RequestParam("docId") Long docId
,HttpServletRequest request ,HttpServletResponse response)){
Document doc = docRepo.findOne(docId);
model.addAtribute("document" , doc);
return "document";
}
}
I'm trying to use EasyUploads-addon for Vaadin, but can't get the image shown.
When I click addon's "Choose File"-button, it will ask me to open an file. I choose some .png -file from my images and addon shows the information of the picture beneath it.
Then I press my "Upload"-button, which is currently needed just to show the uploaded image at first.
private void showUploadedImage() {
Object value = upload.getValue();
byte[] data = (byte[]) value;
StreamResource resource = new StreamResource(
new StreamResource.StreamSource() {
private static final long serialVersionUID = 1L;
#Override
public InputStream getStream() {
return new ByteArrayInputStream(data);
}
}, "filename.png");
image.setVisible(true);
image.setCaption("Uploaded image");
image.setSource(resource);
}
upload = EasyUpload's component which is used to choose file
image = Embedded component that I have drawn with the designer to my layout.
But when I look the page with browser the image is not shown. The image is just shown as there is no image at all, just caption will be shown.
HTML-code of the image from the page's source:
<img src="null">
This might be really trivial case, but all the examples that I found was over 3-4 years old and didn't look helpful.
Can someone tell me, how it should be done?
You need to call a setter on UploadField class:
uploadField.setFieldType(FieldType.BYTE_ARRAY);
Working SSCCE:
#Override
protected void init(VaadinRequest request) {
setContent(layout);
final UploadField uploadField = new UploadField();
uploadField.setAcceptFilter(".png");
uploadField.setFieldType(FieldType.BYTE_ARRAY);
uploadField.addListener(new Listener(){
#Override
public void componentEvent(Event event)
{
showUploadedImage(uploadField);
}
});
layout.addComponent(uploadField);
layout.addComponent(image);
}
private void showUploadedImage(UploadField upload) {
Object value = upload.getValue();
final byte[] data = (byte[]) value;
StreamResource resource = new StreamResource(
new StreamResource.StreamSource() {
#Override
public InputStream getStream() {
return new ByteArrayInputStream(data);
}
}, "filename.png");
image.setSource(resource);
}
Produces (after choosing a .png file):
Of course you may want to change type of uploadField listener to more specific one.
Tested on Java 8, Vaadin 7.4.1, Eclipse Luna.