Reputation: 511
I am trying to save image files under a directory that resides in project's resources folder, below code doesn't give any error neither it saves file to the mentioned location, i know saving file to the resources is a bad idea but just giving it a try will move to upload file to S3 bucket later on.
@PostMapping("/add")
public String addBook(@ModelAttribute("book") Book book, HttpServletRequest request) throws IOException {
bookService.save(book);
MultipartFile bookImage = book.getBookImage();
try {
byte[] bytes = bookImage.getBytes();
String bookName = book.getId() + ".png";
BufferedOutputStream bf = new BufferedOutputStream(new FileOutputStream(new File(
"src/main/resources/static/image/books/"+bookName
)));
bf.write(bytes);
bf.close();
} catch (Exception e) {
e.printStackTrace();
}
return "redirect:bookList";
}
Upvotes: 1
Views: 793
Reputation: 2479
Based on your question and comments above. Also as you are thinking of moving from filesystem storage to S3 then you may want to take a look at community project called [Spring Content][1]. This project allows you to manage content (i.e. your generated book images) and associate them with your Spring Data Entities. It provides the same programming model as Spring Data, just for unstructured content like files, images, videos etc.
For example, assuming you are using Spring Data, you could add this to your projects as follows.
pom.xml (for Spring Web MVC. Spring Boot Starters also available)
<!-- Spring dependencies -->
...
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs</artifactId>
<version>1.0.0.M11</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest</artifactId>
<version>1.0.0.M11</version>
</dependency>
StoreConfig.java
@Configuration
@EnableFilesystemStores
@Import(RestConfiguration.class)
public class EnableFilesystemStoresConfig {
@Bean
File filesystemRoot() throws IOException {
return new File("/path/to/your/book/images");
}
@Bean
FileSystemResourceLoader fileSystemResourceLoader() {
return new FileSystemResourceLoader(filesystemRoot().getAbsolutePath());
}
}
BookImageStore.java
@StoreRestResource(path="bookImages")
public interface BookImageStore extends ContentStore<Book, String> {
}
And to add Spring Content-annotated fields to your Spring Data entities, like this:
Book.java
@Entity
public class Book {
@Id
@GeneratedValue
private long id;
...other existing fields...
@ContentId
private String contentId;
@ContentLength
private long contentLength = 0L;
@MimeType
private String mimeType;
...
}
This is all you need. When your application starts it will see the `spring-content-fs` dependency on your classpath and the BookImageStore interface and it will inject a file-based implementation. Moreover, it will see the spring-content-rest dependency and inject an @Controller implementation providing a REST API for handling your book images that will forward REST calls onto the BookStoreImage so you dont have to worry about implementing any of this yourself.
So:
`POST /bookImages/{bookId} -F "image=@/some/path/to/an/image.jpg"`
will upload `image.jpg` to `/path/to/your/uploaded/images/` and update the fields on the Book entity so the content is associated.
`GET /bookImages/{bookId}` -H 'Accept: image/jpeg'
will fetch it again.
A couple of additional notes;
- I would strongly recommend that you use a path outside of src/resources so that have more flexibility with how you deploy your war/jar
- if later on you want to change the backend storage from the filesystem to s3 all you would have to do it switch out the `spring-content-fs` dependency for `spring-content-s3` and update the StoreConfig to provide an S3 client bean instead of a FilesystemResourceLoader bean.
HTH
[1]: https://paulcwarren.github.io/spring-content/
Upvotes: 1