I'm developing a web application with spring boot. In application, I upload a file and copy to the local folder after that file absolute path is saved in the database. So I have file and I know where it is but I can't reach it in localhost. I know in spring has a static folder for static files but I don't want to copy a file because I will use this data in other applications.
For example:
Local file location: /Users/user/data/image.png
I want to reach like that: http://localhost:8080/data/image.png
Edit: I find the solution. I used MvcUriComponentsBuilder for this.
String url = MvcUriComponentsBuilder.fromMethodName(FileController.class,"serveFile",resource.getFilename()).build().toString();
it's return right value of controllers method.
Method:
#GetMapping("/files/{filename:.+}")
#ResponseBody
public ResponseEntity<Resource> serveFile(#PathVariable String filename) {
Resource file = storageService.loadAsResource(filename);
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + file.getFilename() + "\"").body(file);
}
I think issue is with url you are using. Change it to:
#RequestMapping("/data/{filename:.+}")
this will work.
Related
I'm testing an API with rest assured, programming language is JAVA, I'm having little issue, the issue is , I have to send an image using rest assured, and it's being sent successfully locally, but when i push it to git , having problem with specifying the path, and all my tests are run on TeamCity , and I get my cucumber report, report as follows
java.io.FileNotFoundException: C:\Users\nameOfUser\Downloads\38250987.jpeg (The system cannot find the path specified)
I hope I have delivered the issue descriptive enough, in case if u have any questions,doubts please do ask your questions, hoping for your help and cooperation, thanks in advance!
the code as follows
public static Response SendAnImage(String prodID,Cookies cookies) {
File file = new File("C:\\Users\\userName\\Downloads\\38250987.jpeg");
System.out.println("is file found ----> "+file.exists());
Response response = given()
.multiPart("file", file, "image/jpeg")
.when()
.cookies(cookies)
.post("/api/product/"+prodID+"/file/false");
return response;
}
You can put your file in src/test/resources folder, then create a new File like this:
File file = new File("src/test/resources/38250987.jpeg");
You cannot refer to local files in your tests. You need to include the picture file to your Git repository, load them as a resource in the test and then use the method in REST-assured that accepts a byte array instead of a file:
multiPart(String controlName, String fileName, byte[] bytes)
The solution here helps me get absolute path to assets in class-path (context)
Tapestry 5 - Dynamically generate URL of file in web app context folder in Java code
Is there a way to do the same for assets stored in META-INF/assets (Tapestry 5.4 way of storing assets)?
Specifically, I'd like to inject the path of the a .html (static) file I've created in META-INF/assets folder..
at the moment I have:
public String getMyHtml() {
String clientURL = assetSource.getContextAsset("html/myhtml.html", locale).toClientURL();
return clientURL;
}
and the tml file has:
"{ url: '${getDeltaHtml()}' }"
This works if "myhtml.html" file is located in class path folder (WEB-INF). It does not work if its in META-INF/assets folder, which is where I'd like to put it
You can get hold of the assets stored under assets by this.
First you have to inject the following.
#Inject
private AssetSource assetSource;
#Inject
private ThreadLocale threadLocale;
After that you can use the following to get the Assets.
Asset asset = assetSource.getAsset(null, "classpath:META-INF/assets/myhtml.html", threadLocale.getLocale());
I have a folder inside resources folder where I want to upload media files. But I am constantly getting 'No file or directory found' error.
Here is what I have in my controller
#Autowired
ServletContext servletContext;
#RequestMapping(value = "/uploads", method = RequestMethod.POST)
public String insert(#RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
// String path = new
// ClassPathResource("/src/main/resources/uploads").getPath();
// FileCopyUtils.copy(file.getBytes(), new File(path));
String webappRoot = servletContext.getRealPath("/");
String relativeFolder = File.separator + "resources" + File.separator + "uploads" + File.separator;
System.out.println(webappRoot);
System.out.println(relativeFolder);
String filename = webappRoot + relativeFolder + file.getOriginalFilename();
FileCopyUtils.copy(file.getBytes(), new File(filename));
return "uploaded successfully";
}
And here is the error I am getting constantly
SEVERE: Servlet.service() for servlet [api] in context with path [/ek-service] threw exception
java.io.FileNotFoundException: /home/ekbana/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ek-service/resources/uploads/2.jpg (No such file or directory)
I have searched all over the web tried ResourceLoader and ClassPath. But still no success figuring it out.
Resources should be considered read-only, they are not accessible through the file system, but are embedded in the war/jar when you deploy an application.
You must write the file to a path on the file system that exists and that your application has write access to.
You can write to a temporary file, it has the benefit that you most certainly will have write access to it. Useful for testing until you figure out a permanent location to store the file, or for cases when permanent storage is not necessary. See example: http://www.mkyong.com/java/how-to-create-temporary-file-in-java/
I have Spring MVC web app running on Tomcat.
I upload a file and save it in the /tmp folder on the file system.
Then I need to show a link to that file in the view (Thymeleaf), so that the user can download the file by clicking on the link. How to do that?
I've heard about configuring Tomcat to allow a specific context to link to a folder on the FS, but not sure how to do that or if that is the only solution. Please help.
The way I approach this is slightly different. Basically I use two controller actions for handling file uploads, one for uploading, and for downloading (viewing) files.
So upload action would save files to some preconfigured directory on the file system, I assume you already have that part working.
Then declare download action similar to this
#Controller
public class FileController {
#RequestMapping("/get-file/{filename}")
public void getFileAction(#RequestParam filename, HttpServletResponse response) {
// Here check if file with given name exists in preconfigured upload folder
// If it does, write it to response's output stream and set correct response headers
// If it doesn't return 404 status code
}
}
If you want to make impossible to download file just by knowing the name, after uploading file, save some meta info to the database (or any other storage) and assign some hash (random id) to it. Then, in getFileAction, use this hash to look for file, not the original filename.
Finally, I would discourage using /tmp for file uploads. It depends on the system/application used, but generally temp directory are meant, as name suggest, for temporary data. Usually it is guaranteed data in the temp directory will stay for "reasonable time", but applications must take into account that content of temp directory can be deleted anytime.
This is the precisely setup that worked for me (Tomcat 8, SpringMVC, boot):
server.xml:
<Context docBase="C:\tmp\" path="/images" />
In the controller:
public String createNewsSource(#ModelAttribute("newsSource") NewsSource source, BindingResult result, Model model,
#RequestParam("attachment") final MultipartFile attachment) {
new NewsSourceValidator().validate(source, result);
if (result.hasErrors()) {
return "source/addNewSource";
}
if (!attachment.isEmpty()) {
try {
byte[] bytes = attachment.getBytes();
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(new File("/tmp/" + attachment.getOriginalFilename())));
stream.write(bytes);
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
source.setLogo("images/" + attachment.getOriginalFilename());
newsSourceService.createNewsSourceIfNotExist(source);
return "redirect:/sources/list";
}
As you can see I am saving the file to /tmp, but in the DB (source.setLogo()), I am pointing to images as mapped in server.xml
Here's where I found about Tomcat config:
If the images 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 tag:
This way they'll be accessible through http://example.com/images/....
SO answer to a similar question
I am using Spring Framework's MultipartFile to allow a user to upload a picture to a profile. I've configured DispatcherServlet in a servlet initializer class that extends AbstractAnnotationConfigDispatcherServletInitializer. In that class, I've overridden the customizeRegistration() method as follows:
#Override
protected void customizeRegistration(Dynamic registration) {
registration.setMultipartConfig(new MultipartConfigElement("/tmp/practicewellness/uploads", 2097152, 4194304, 0));
}
The MultipartFile's transferTo() method calls for a file location in the filesystem where the uploaded file will be written temporarily. Can this location be anywhere? When I used the following location in the method:
profilePicture.transferTo(new File("tmp/practicewellness/" + employee.getUsername() + ".jpg"));
... I get the following error:
Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [C:\Users\kyle\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\work\Catalina\localhost\practicewellness\tmp\practicewellness\uploads] is not valid
So I can see that it's looking for this file location deep inside one of my Eclipse plugins. I don't understand why it looks there. When I look there, the "tmp" directory is not there. But regardless, is it okay for me to go into that plugin and create the directory there? Or is there a better way to smooth this out?
I've uploaded files using Spring mvc, but never used transferTo(), I just assume that your problem is due to "No existence of specified path" because there wont be a path ending with .jpg. Try it like this.
String path = "/tmp/practicewellness/";
File dirPath = new File(path);
if (!dirPath.exists()) {
dirPath.mkdirs();
}
And then execute the transferTo() code.
Also do not set the path directly like you've done. Since you're doing it in spring, so I assume you want the folder to be in your Project path not the eclipse's metadata path. So change your path to this.
String path = request.getSession().getServletContext().getRealPath("/tmp/practicewellness/");
It will create a folder inside your Project's Webapp folder using mkdir. If you want to save differentiate the files for each user, you can create a folder for each user by using this below path.
String path = request.getSession().getServletContext().getRealPath("/tmp/practicewellness")+"/"+employee.getUsername()+"/";