Upload and download image to project folder using Spring Boot

0

I'm developing a web module that I need to upload an image. Do save in the project folder, I'm using the Apache Commons Io:

public class FileUtil {

    public static void saveFile(String path, MultipartFile file){

        File saveFile = new File(path);
        try {
        FileUtils.writeByteArrayToFile(saveFile, file.getBytes());
        } catch (IOException e) {
        e.printStackTrace();
        }
    }
}


@Autowired
private ServletContext servletContext;

@RequestMapping(value = "/salvar", method = RequestMethod.POST)
public String salvar(Event evento, Model model, @RequestParam("file") MultipartFile file) {
    if (file != null && !file.isEmpty()) {
        String path = servletContext.getRealPath("/") + "resources/imagens/" + evento.getName() + ".png";
        FileUtil.saveFile(path, file);
    }
    service.salvar(evento);
    return "redirect:/evento/formulario";
}

I'm still able to save, but how can I make this path where the image was saved, in a link that can download the image and add it as an attribute of the Event class?

    
asked by anonymous 07.02.2017 / 22:11

1 answer

2

Create a method that receives the name of an image and downloads it, eg:

@Controller
@EnableAutoConfiguration
public class Main {

    @Autowired
    private ServletContext servletContext;

    //Lista as imagens dentro da pasta resources/imagem numa JSP
    @RequestMapping("imagens")
    public ModelAndView imagens() throws IOException {

        ModelAndView mv = new ModelAndView("image-list");
        Set<String> nomeDasImagens = servletContext.getResourcePaths("/resources/imagens/").stream()
                                                    .map(FilenameUtils::getBaseName)
                                                    .collect(Collectors.toSet());
        mv.addObject("imagens", nomeDasImagens);
        return mv;
    }

    //Faz o download da imagem com o nome informado
    @RequestMapping(value = "download/{nome}", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<InputStreamResource> downloadImage(@PathVariable String nome) {
        InputStream is = servletContext.getResourceAsStream("/resources/imagens/" + nome + ".png");
        if(is == null) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
        }

        //Faça o que quiser aqui
        //Como criar um Event e atribuir o nome ou o caminho da imagem a ele

        return ResponseEntity.ok()
                .contentType(MediaType.IMAGE_PNG)
                .header("Content-disposition", "attachment; filename=" + nome + ".png")
                .body(new InputStreamResource(is));
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Main.class, args);
    }
}

JSP page that lists all images:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Imagens</title>
    </head>
    <body>
        <c:forEach var="imagem" items="${imagens}">
            <a href="download/${imagem}">${imagem}</a><br />
        </c:forEach>
    </body>
</html>

Edit:

To only display the image, you can remove the header from ResponseEntity by doing so:

return ResponseEntity.ok()
                .contentType(MediaType.IMAGE_PNG)
                .body(new InputStreamResource(is));

Another option is to access it statically:

To do this add the following method:

@RequestMapping("imagens-estaticas")
public ModelAndView imagensEstaticas() throws IOException {

    ModelAndView mv = new ModelAndView("image-list");
    Map<String, String> nomeDasImagens = servletContext.getResourcePaths("/resources/imagens/").stream()
                                                .collect(Collectors.toMap(FilenameUtils::getBaseName, String::toString));
    mv.addObject("imagens", nomeDasImagens);
    return mv;
}

And change the JSP to:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Imagens</title>
    </head>
    <body>
        <c:forEach var="imagem" items="${imagens}">
            <a href="${imagem.value}">${imagem.key}</a><br />
        </c:forEach>
    </body>
</html>

Edit 2:

In order to download images in any format:

@RequestMapping("imagens")
public ModelAndView imagens() throws IOException {

    ModelAndView mv = new ModelAndView("image-list");
    Set<String> nomeDasImagens = servletContext.getResourcePaths("/resources/imagens/").stream()
                                                .map(FilenameUtils::getName)
                                                .collect(Collectors.toSet());
    mv.addObject("imagens", nomeDasImagens);
    return mv;
}

@RequestMapping(value = "download/{nome:.+}", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<InputStreamResource> downloadImage(@PathVariable String nome) throws FileNotFoundException {
    InputStream is = servletContext.getResourceAsStream("/resources/imagens/" + nome);
    if(is == null) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
    }
    return ResponseEntity.ok()
            .contentType(MediaType.parseMediaType("image/" + FilenameUtils.getExtension(nome)))
            .header("Content-disposition", "attachment; filename=" + nome)
            .body(new InputStreamResource(is));
}
    
08.02.2017 / 20:03