I'm trying to upload an image with spring MVC in src/main/webapp/resources to display it in an img tag (<img src="<c:url value="/resources/images/image.jpg" />" alt="image" />) in my jsp. I have this controller :
#Controller
public class FileUploadController implements ServletContextAware {
private ServletContext servletContext;
private String rootPath;
#RequestMapping(value = "/uploadSingleFile", method = RequestMethod.GET)
public ModelAndView uploadSingleFileFormDisplay() {
return new ModelAndView("uploadSingleFile");
}
#RequestMapping(value = "/uploadSingleFile", method = RequestMethod.POST)
public #ResponseBody String uploadSingleFileHandler(#RequestParam("file") MultipartFile file) {
String filename = file.getOriginalFilename();
rootPath = servletContext.getRealPath("/") + "resources/uploads";
if (!file.isEmpty()) {
try {
Document document = new Document();
Image image = new Image();
byte[] bytes = file.getBytes();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File(
rootPath + "/" + filename
)));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + filename + "!";
} catch (Exception e) {
return "You failed to upload " + filename + " => " + e.getMessage();
}
} else {
return "You failed to upload " + filename + " because the file was empty.";
}
}
(...)
}
How do I build the rootPath to have an absolute path of my system like this : C:/absolute/path/to/webapp/resources or /absolute/path/to/webapp/resources ?
I would say it is not good idea. In fact src folder does not exist. The resources are moved on compile.
Moreover it's not good to place uploaded under web root. First because on restart the web root could be replaced with a new structure from WAR and because of security reasons. You get a potential hole letting something to be uploaded in the place where it could be run.
Instead define an upload path property and use it to store uploaded files and download them if necessary.
UPDATE:
#Value("${myUploadPath}")
private String upload;
and specify property in e.g. application.properties or as JVM argument on start
-DmyUploadPath="C:/absolute/path/to"
Related
I have problem with upload file to local WebDav. So far i have:
public interface IStorageService {
URI SaveFile(String filename, InputStream inputStream);
}
#Component
public class LocalStorageService implements IStorageService {
#Value( "C:\temp" )
private String filestorePath;
public URI SaveFile(String filename, InputStream inputStream) {
var rootLocation = Paths.get(filestorePath);
var filePath = rootLocation.resolve(filename);
try {
Files.copy(inputStream, filePath);
} catch (IOException e) {
throw new RuntimeException("Failure save file to " + filename + " in " + filestorePath + "." + e.getMessage(), e);
}
return filePath.toUri();
}
}
and controller
private final DocumentService documentService;
public DocumentController(DocumentService documentService) {
this.documentService = documentService;
}
#RequestMapping(method = RequestMethod.POST)
public DocumentModel handleFileUpload(#RequestParam("file") MultipartFile file) throws IOException {
return documentService.handleFileUpload(file.getOriginalFilename(), file.getInputStream());
}
And it is works correctly, the file is uploaded to C:/temp...
Now I would like to do the same but upload file to local WebDav. When i change in #Value "C:\temp to "http://localhost" (this is ma webdav location) i have:
invalidpathexception: illegal char <:> at index 4: http://localhost
or when I declare http//localhost without <:>
nosuchfileexception: http\localhost
How can I write my code to upload file directly to WebDav.
Parameters of SaveFile method cannot be changed, I need do it with Name as String and InputStream.
I tried with Sardine but to no avail. Could someone help me, give any tips or maybe suggestion of code ?
Greetings !
You can get the path where your web app/ war/ servlet / controllers are deployed :
ServletContext context = getContext();
String fullPath = context.getRealPath("/WEB-INF/test/foo.txt");
For a Spring project, in controller
'#Autowired
'ServletContext context;
And in controller method :
'String uploadPath = context.getRealPath("") + File.separator + UPLOAD_DIRECTORY;
And the real file name, but what if a user uploads same file twice or 2 users upload file with same name?
Better to put in sub directory with user id/ user name and maybe date time or some other identifier like TXN id + some fixed text like
' String fileName = context.getRealPath("") + File.separator + userId + readlName + "xyz."
extnFromMimeType;
And store the path in data base for this transaction/ user as per your busibess use case.
if mime type is image/PMG then extnFromMimeType will be "png"; if jpeg or jpg then "jpg"
See
File path to resource in our war/WEB-INF folder?
how to get getServletContext() in spring mvc Controller
In Spring MVC, how can I set the mime type header when using #ResponseBody
https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
If can be many images per user/ transaction can also use createTemp File to get a unique file name
using a UUID also possible ... https://stackoverflow.com/a/1293712/1643558 or a large random number
I have a small problem which I've been unable to solve for a few hours. I am basically trying to stream an excel file from the resources folder withing a jar. The file has around 9KB in my file manager, however, when I download it by visiting the REST endpoint I receive a 13/14KB file which can no longer be opened by excel. The metadata is set correctly, as is the filename. I suspect the streaming/copying process is somehow corrupting the file. Here you may see the code snippet:
public void getTemplateByDataType(HttpServletResponse response, DataType dataType) {
String fileName = "excel_template.xlsx";
String templateDirectory = "templates";
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
InputStream data = this.getClass().getClassLoader().getResourceAsStream(templateDirectory + "/" + fileName); // loading file from resources folder
try {
IOUtils.copy(data, response.getOutputStream()); // copying to httpservletresponse output stream
} catch (IOException e) {
//...
}
}
I've already tried reading from a simple text file in the same location in order to verify whether the getResourceAsStream call works and this is the case. So I am somehow breaking something with the IOUtils.copy I guess? Does anybody have any suggestions why this simple code snippet breaks my xlsx files?
Just to get the full picture, the controller is relatively simple:
#GetMapping(value = "/templates", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public #ResponseBody
void getFileTemplate(HttpServletResponse response,
#ApiParam(value = "Type of data import", required = true) #RequestParam String dataType) {
importService.getTemplateByDataType(response, DataType.fromValue(dataType));
}
Try Streaming Output. Maybe this would help you Example of using StreamingOutput as Response entity in Jersey
If you want to download as an attachment, then return the Response like below:
Response.status(Response.Status.OK)
.header(HttpHeaders.CONTENT_DISPOSITION,
String.format("attachment; filename=\"download.gz\""))
.entity(streamingOutput)
.build();
StreamingOutput streams the content of the file and at the client end, it will be downloaded as an attachment.
try to copy this file directly to your output stream.
#GetMapping(value = "/templates", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public #ResponseBody
void getFileTemplate(HttpServletResponse response,
#ApiParam(value = "Type of data import", required = true) #RequestParam String dataType) {
String fileName = "excel_template.xlsx";
String templateDirectory = "templates";
Path templateFilePath = Paths.get(getClass().getClassLoader().getResource(templateDirectory + "/" + fileName).toURI());
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
try {
FileCopyUtils.copy(new BufferedInputStream(new FileInputStream(templateFilePath.toFile())), response.getOutputStream());
response.getOutputStream().flush();
response.getOutputStream().close();
} catch (IOException e) {
//...
}
}
```
I am using spring boot and I want to upload an image via a form.
It works, but there are 2 problems:
1) I do not know how to validate the file to make sure it is either jpg or png
2) I can upload only to the root folder, not to the static folder, I do not know how to set the correct path to the resources/static folder
#PostMapping("/add")
public String add(#Valid Product product, #RequestParam MultipartFile file, BindingResult bindingResult,
RedirectAttributes redirectAttributes, Model model) {
...
try {
byte[] bytes = file.getBytes(); // how to validate this?
Path path = Paths.get( file.getOriginalFilename()); // how to set path here?
Files.write(path, bytes);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded '" + file.getOriginalFilename() + "'");
} catch (IOException e) {
System.out.println("!!!!!!!!!!!!! Image uploaded problem !!!!!!!!!!!!!!");
e.printStackTrace();
}
...
}
To get file extension
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
Path
InputStream in = file.getInputStream();
File destination = new File("/some-location/" + file.getOriginalFilename());
FileUtils.copyInputStreamToFile(in, destination);
I am new to the mockmvc api.
I am trying to write units for my controllers and one of the method performs download. Please find the code snippet:
Controller :
#RequestMapping(value = "/download-template", method = RequestMethod.GET, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
#ResponseBody
public FileSystemResource downloadTemplate(HttpServletRequest request,
HttpServletResponse response) {
logger.info("User ID: " + request.getAttribute("userId")
+ " - POST: /upload/download-template");
String rootDir = config.getBaseFolder();
DownloadUploadTemplateResponse res = uploadService.downloadTemplate(
rootDir, false);
response.setHeader("Content-Disposition",
"attachment; filename=" + res.getFileName());
return new FileSystemResource(res.getTemplateFile());
}
Unit test code:
#Test
public void testDownloadTemplate(){
DownloadResponse res = new DownloadResponse();
String templateFile = "upload-template.xlsx";
String fileName = System.getProperty("java.io.tmpdir") + templateFile;
res.setFileName(fileName);
res.setTemplateFile(templateFile);
when(config.getBaseFolder()).thenReturn(System.getProperty("java.io.tmpdir"));
when(uploadService.downloadTemplate( System.getProperty("java.io.tmpdir"), false)).thenReturn(res);
//File file = new File(fileName);
FileSystemResource resource = new FileSystemResource(res.getTemplateFile());
try{
ResultActions action = mockMvc.perform(get("/upload/download-template").contentType(APP_OCTET_STREAM_VALUE_UTF8));
action.andExpect(header().string("Content-Disposition",
"attachment; filename=" + res.getFileName()));
action.andExpect(status().isOk());
}catch(Exception e){
e.printStackTrace();
fail();
}
}
Below line throws java.io.FileNotFoundException: upload-template.xlsx (The system cannot find the file specified):
ResultActions action = mockMvc.perform(get("/upload/download-template").contentType(APP_OCTET_STREAM_VALUE_UTF8));
Please guide what additional I need to add in the httprequestbuilder to resolve this issue.
My bad .. the error was clear enef to fix the issue . The problem was the file was not physically present :).
So by placing the file in the temp folder helped me resolve the issue. Feel like ahhh .
I'm building a java application with tomcat embedded and jersey REST.
What i need to do is to implement a VERY simple (and single) file upload inside this application but i can't find anywhere a guide for my context...i just found a file upload solution but NOT with embedded tomcat.
Any suggestions?
Thanks everyone in advice and sorry for my English
If you are using Spring Boot for Tomcat embedded, then below code example will help you..
#Controller
public class FileUploadController {
#RequestMapping(value="/upload", method=RequestMethod.GET)
public #ResponseBody String provideUploadInfo() {
return "You can upload a file by posting to this same URL.";
}
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file){
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name)));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + name + "!";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name + " because the file was empty.";
}
}
}
With ref. of
https://spring.io/guides/gs/uploading-files/