I am developing a Rest API using Spring Boot and AngularJS in the client side, i am uploading files to /resources/static/upload with Spring using the RestController below and using them in the client side
#RestController
#CrossOrigin("*")
public class FilmController {
#Autowired
private FilmRepository filmRepository;
#RequestMapping(value = "/films", method = RequestMethod.POST)
public void saveFilm(#RequestParam("file") MultipartFile file) throws Exception {
File convFile = new File("src/main/resources/static/upload/"+file.getOriginalFilename());
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
Blob blob = new SerialBlob(file.getBytes());
fos.write(file.getBytes());
fos.close();
System.out.println(convFile.getName());
filmRepository.save(new Film(convFile.getName(), blob));
}
#RequestMapping(value = "/films", method = RequestMethod.GET)
public List<Film> getAllFilms() {
return filmRepository.findAll();
}
}
Here is how i accessed the uploaded image "image.jpg"
<img src="http://localhost:8080/upload/image.jpg" />
But, when i ran mvn package and i launch my application jar file, i can't access the uploaded image in the client side, i get 404 not found.
Can someone explain how Spring store and refer to static resources and how can i resolve this problem.
I'm using absolute path to the directory and this works in both cases: when it's runing with mvn spring-boot:run and when it's running as java -jar app.jar.
For example, you could try to save uploads to /opt/upload (make sure that it exists and user has permissions to write into it):
File convFile = new File("/opt/upload/"+file.getOriginalFilename());
Also you should configure Spring to serve uploads from this directory:
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/upload/**")
.addResourceLocations("file:/opt/upload/");
}
}
More info about configuring resource handler: http://www.baeldung.com/spring-mvc-static-resources
First of all you cannot store in the folder structure you see in your IDE that is not how your code will be in a deployed package
File convFile = new File("src/main/resources/static/upload/"+file.getOriginalFilename());
store using relative path
File convFile = new File("/static/upload/"+file.getOriginalFilename());
and also add the resource location mapping in spring config for your image upload folder .
<mvc:resources mapping="/upload/**" location="/static/upload/" />
Related
I've created a Restful service with Spring MVC as shown below. I called it using Postman. I placed a breakpoint on 'return "hello World"'. There's no hit on the breakpoint with the error message "Required request part 'file' is not present".
However, if I comment out the '#RequestParam("file")' annotation, the breakpoint is hit with the parameter "file" being null.
What could have gone wrong? Very puzzled.
#RestController
#RequestMapping("/dp")
public class DpWebService implements IDpWebService {
#Override
#Bean
public MultipartConfigElement multipartConfigElement() {
return new MultipartConfigElement("");
}
#Override
#Bean
public MultipartResolver multipartResolver() {
org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(1000000);
return multipartResolver;
}
#Override
#RequestMapping(path = "/send", method = RequestMethod.POST, consumes = "multipart/form-data")
public String sendManifest(#RequestParam("file") MultipartFile file) {
return "Hello World";
}
}
Postman
Postman Header
Check your POSTMAN request Configuration. I think you have not changed the input type to File from Text. Uploading images, check the images. Hover the mouse over that area in Postman and select File from the drop-down menu.
Having Beans defined in your RestController is not a good design. Please separate out a Configuration class with #Configuration annotation and define your beans. The reasons being: Single Responsibility Principle - each class should only do about one thing.
https://java-design-patterns.com/principles/#single-responsibility-principle
#RequestParam might not be working for you because of the nature of the data that is contained in the file that you are sending through the request. RequestParam is likely to be used with name-value form fields. For complex data like json/xml it is advisable to use #RequestPart instead.
Instead of the #RequestParam annotation use the #RequestPart annotation.
Annotation that can be used to associate the part of a
"multipart/form-data" request with a method argument.
Try using it like :
#RestController
#RequestMapping("/dp")
public class DpWebService implements IDpWebService {
#Override
#Bean
public MultipartConfigElement multipartConfigElement() {
return new MultipartConfigElement("");
}
#Override
#Bean
public MultipartResolver multipartResolver() {
org.springframework.web.multipart.commons.CommonsMultipartResolver multipartResolver = new org.springframework.web.multipart.commons.CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(1000000);
return multipartResolver;
}
#Override
#RequestMapping(path = "/send", method = RequestMethod.POST, consumes = "multipart/form-data")
public String sendManifest(#RequestPart("file") MultipartFile file) {
return "Hello World";
}
}
Also make sure that the request from the postman is getting triggered correctly :
Remove any un wanted request params from postman.
Make sure that under 'Body' tab the form-data is selected. Also make
sure that when selected the file in the key the name is provided as
'file' and type is also selected as file instead of text.
This is my working example.
#PostMapping("/uploadFile")
public UploadFileResponse uploadFile(#RequestParam("file") MultipartFile file) {
String fileName = fileStorageService.storeFile(file);
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath().path("/downloadFile/")
.path(fileName).toUriString();
return new UploadFileResponse(fileName, fileDownloadUri, file.getContentType(), file.getSize());
}
application.properties
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=200MB
# Max Request Size
spring.servlet.multipart.max-request-size=215MB
## File Storage Properties
# Please change this to the path where you want the uploaded files to be stored.
file.upload-dir=C://Users//abc//Documents//
I an creating an endpoint with spring boot...i can upload image to folder and save it via postman everythink works good.
i have a problem with get method when i am adding the value #RequestMapping value = "getImage/{imageName:.+}" in postman i add http://localhost:8080/api/images/getImage/{burger+png}
is that corect ???
#RequestMapping(value = "api/images")
public class ImageController {
#Autowired
public ImageService imageService;
#PostMapping(value ="upload")
public ResponseEntity uploadImage(#RequestParam MultipartFile file){
return this.imageService.uploadToLocalFileSystem(file);
}
#GetMapping(
value = "getImage/{imageName:.+}",
produces = {MediaType.IMAGE_JPEG_VALUE,MediaType.IMAGE_GIF_VALUE,MediaType.IMAGE_PNG_VALUE}
)
public #ResponseBody byte[] getImageWithMediaType(#PathVariable(name = "imageName") String fileName) throws IOException {
return this.imageService.getImageWithMediaType(fileName);
}
}
what should be the correct request url ???
It seems like it's reaching the backend fine, but failing to find path. Usually API endpoints end with parameters with a slug or query param. You can try either of the following to see if it works:
http://localhost:8080/api/images/getImage/burger.png
http://localhost:8080/api/images/getImage?imageName=burger.png
Keep in mind, you want to make sure that file exists at the path it's mentioning at the very top of the trace in the JSON response. This may depend on how you uploaded the file and with what name.
I have the following code snippet:
#RestController
#RequestMapping("/dropbox")
public class DropboxController {
private static final Logger logger = LoggerFactory.getLogger(DropboxController.class);
#Autowired
DropboxService dropboxService;
#Autowired
DbxClientV2 dropboxClient;
#PostMapping("/upload")
public String handleFileUplad(#RequestParam("file") MultipartFile file, #RequestParam("filePath") String filePath) throws Exception {
dropboxService.uploadFile(file, filePath);
return "You successfully uploaded " + filePath + "!!";
}
Now I want to test whether the upload works. How can I do this? How would be the syntax when I try it with curl?
Source: https://www.mkyong.com/spring/curl-post-request-examples/
To POST with a file, add this -F file=#"path/to/data.txt"
$ curl -F file=#"path/to/data.txt" http://localhost:8080/dropbox/upload
Also as an alternative you can use Postman
Add form-data as body with 2 parameters and select the type as file
i want to read file from controller like this:
#Controller
public class HomeController {
#RequestMapping(value = {"/"}, method = RequestMethod.GET)
public String showHomePage(ModelMap model) throws IOException, SAXException, ParserConfigurationException {
List<User> users = XmlParser.parse("Sum_and_clients.xml");
return "home";
}
But when I start the server it wants download it from apache-tomcat\bin. Despite the fact that Sum_and_clients.xml is located near the HomeController.java. How change this absoulte tomcat path, to path in my project?
I solved my problem.
URL url = HomeController.class.getResource("Sum_and_clients.xml");
File file = new File(url.getPath())
This file should be placed into [{Your project name}\target\ {Your project name} \WEB-INF\classes\ {Your package to HomeController}
I want send my android .apk file to my client(browser) from java restful web service.I try to use bellow code. But it produce a file named "MyPath" without any file extension (require .apk).Thanks in advance
#Path("MyPath")
public class MyPathResource {
#Context
private UriInfo context;
/**
* Creates a new instance of MyPathResource
*/
public MyPathResource() {
}
#GET
#Produces("application/vnd.android.package-archive")
public File getFile() {
// return my file
return new File("E:\\CommandLineAndroidProjet1\\bin\\FirstCommandLineApp-release.apk");
}
}
Try creating an explicit javax.ws.core.Response:
return Response.status(Response.Status.OK)
.entity(entity)
.header("Content-Disposition", "attachment; filename=" + fileName)
.build();
while entity is your file as byte array and fileName is the file name with .apk suffix.