I've been trying to display an image using thymeleaf for awhile and having issues with it saving it as a byte array was no problem, however displaying it is extremely (for me at least) I followed a post with the question that was asked about it and had no results sadly, was hoping someone could help me with this problem
Controller trying to display the image
#GetMapping("/home")
public String index(Model model){
model.addAttribute("clothingItems", itemService.findAll());
return "index";
}
#GetMapping("/display/image/{id}")
public void displayItemImage(#PathVariable int id, HttpServletResponse response) throws IOException{
response.setContentType("image/*");
Item item = itemService.findItemById(id);
InputStream is = new ByteArrayInputStream(item.getImage());
IOUtils.copy(is, response.getOutputStream());
}
My Entity class
public class Item {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "post")
private String text;
#Lob
#Column(name = "img")
private byte[] image;
#OneToOne(cascade = {CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH})
#JoinColumn(name = "category_id")
private Category category;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
Trying to display it with thymeleaf
<div class="category-1">
<h2>Headwear</h2>
<div class="image-container" th:each="clothing : ${clothingItems}">
<img th:src="#{'display/image/' + #{clothing.image}}">
</div>
</div>
I tried following this post How to display byte array from a model in Thymeleaf and ended up with an empty image
im also getting a NumberFormatException when I try to open the empty image in a new tab
In your thymeleaf template for the code
<img th:src="#{'display/image/' + #{clothing.image}}">
The src should point to #{'/display/image/'} you need to insert '/' that specifies you are referring to the root of your application also instead of #{clothing.image} it should be ${clothing.image} as it's a variable, not a link.
So the above line code of should be
<img th:src="#{'/display/image/' + ${clothing.id}}">
Try this in your displayItemImage method it's not advisable to directly write the content to the response entity and also change the MIME-TYPE to image/png or image/jpeg. Here's a better approach.
#GetMapping("/display/image/{id}")
public ResponseEntity<byte[]> displayItemImage(#PathVariable int id) {
Item item = itemService.findItemById(id);
byte[] image = item.getImage();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<>(image, headers, HttpStatus.OK);
}
For testing the method I have used H2 database. Here's the test code with the results.
#SpringBootTest
class ShoppingSiteApplicationTests {
#Autowired
ItemService itemService;
#Autowired
private UserController yourController;
private MockMvc mockMvc;
#Test
void testMethod() throws Exception {
mockMvc = MockMvcBuilders.standaloneSetup(yourController).build();
byte [] mockByte = {0x01, 0x02, 0x03};
Item item = new Item();
item.setImage(mockByte);
itemService.saveItem(item);
MvcResult result = mockMvc.perform(get("/display/image/" + item.getId()))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.IMAGE_JPEG))
.andReturn();
byte[] responseBody = result.getResponse().getContentAsByteArray();
assertArrayEquals(item.getImage(), responseBody);
}
}
Here's the live result from your Github Repository you can see the image displayed. The problem may be in the MYSQL setup or so, if yes please raise another question with the code. Hope it helps
Related
The browser sends the following object to the backend:
Now I would like to store the data in my database. So I have an entity that looks like this:
#Entity
public class NewQuote {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String description;
#ElementCollection(targetClass = Details.class)
private List<Details> details = new ArrayList<>();
public NewQuote(String description, ArrayList<Details> details) {
this.description = description;
this.details = details;
}
#Embeddable
public class Details {
private String description;
private String label;
public Details(String description, String label) {
this.description = description;
this.label = label;
}
public Details() {}
}
Controller
#PostMapping(value = "/save-quote", produces = MediaType.APPLICATION_JSON_VALUE)
public void saveQuote(#RequestBody Map<String, String> data) {
newQuoteService.saveQuote(data);
}
Service
public void saveQuote(Map<String, String> data) {
JSONObject json = new JSONObject(data);
NewQuote newQuote = new NewQuote(
json.getAsString("description"),
json.getAsString("details")
);
newQuoteRepository.save(newQuote);
}
I am getting an error because json.getAsString("details") should not be a string of course. So how can I turn it to ArrayList<Details>?
Add a DTO to manage your json response. You don't need to explicitly use JSONObject because spring already manage the process of mapping under the wood with Jackson.
Also, it is not a good practice to pass your Entities directly into the controller methods.
NewQuoteDto.java
public class NewQuoteDto {
private Long id;
private String description;
private List<Details> details = new ArrayList<>();
public NewQuoteDto() {
}
// getter and setter or you can use lombok
}
DetailDto.java
public class DetailDto {
private String description;
private String label;
public DetailDto() {}
// getter and setter or you can use lombok
}
Controller
#PostMapping(value = "/save-quote", produces = MediaType.APPLICATION_JSON_VALUE)
public void saveQuote(#RequestBody NewQuoteDto dataDto) {
// here you map dataDto to your model before you call saveQuote
NewQuote data = mapper.map(dataDto, NewQuote.class); // if you use ModelMapper library.
newQuoteService.saveQuote(data);
}
For custom mapping take look here.
I POST some data with Retrofit2 to a Spring Boot REST service and there are a lot of exceptions occurring in the server. This happens when I have relations in my database.
I have a REST service over a Spring Boot application that runs over the Heroku services, I was doing a login and a register tasks with an Android application, I am using Retrofit2 in Android to POST the data to the REST service, everything was working well until for some other reasons I create a relationship between users in my database, this relationship is a "follow", this is, create a relationship in a follow table where I have the ID of the user that is following and an ID of the user that is followed. When I create this relationship into the database and I try to login with the method that I created, I got a bunch of errors into the REST service that I do not know why is this happening.
So in Android I have the call of my Retrofit2 client and a method that creates the service passing as a parameter the UserService.class with the HTTP methods. I also pass as a parameter the user of the class User where have the information that I want to POST, then I call the enqueue method.
RetrofitClient.createService(UserService.class).login(user).enqueue(new CallBack<User>(){
#Override
public void onResponse(Call<User> call, Response<User> response) {
//Some logic here
}
});
Into my UserService.java I have the method that POST the user object information.
public interface UserService {
#POST("login")
public Call<User> login(#Body User user);
}
Now in the backend side I have a REST controller where I have the login endpoint that will be consumed for Retrofit2.
#PostMapping(path = "login", consumes = "application/json", produces = "application/json")
#CrossOrigin(origins = "*", methods= {RequestMethod.GET,RequestMethod.POST})
public Object login(#RequestBody String json) {
//Some logic here
}
As I said this endpoint runs fine when there are no relationships over a user into the DB, but when a user follow another one, this is, when there is a new row into the follow table, lets say:
follow table:
id_follow id_user_follower id_user_following
1 1 2
At the example above the user 1 follows the user 2, and when I try to login, this is, use the login method in the UserService class it throws me a bunch of errors.
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
And this repeat over 300 lines of errors.
The thing here is that between the bunch of error the server return a 200 HTTP response, I managed the exceptions in Spring Boot and I catch that, when I catch I send a code for an error to my Android Retrofit2 client, but the login does not work.
Expected result:
After sending the POST from Retrofit2 to Spring Boot the response have to be a HTTP 200 response but no exceptions have to happen into the server.
Actual result:
There is a 200 HTTP response from the server but there are a lot of exceptions into the server that return an error code to the Android application and the login does not work.
This is the entity that I want to return as JSON from the RestController in Spring Boot.
#Entity
#Table(name = "users")
public class User extends AuditModel{
private static final long serialVersionUID = 1700575815607801150L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idUser;
private String name;
private String lastName;
#Column(name = "nick_name", unique = true)
private String nickName;
private String avatarResource;
#Column(unique=true)
private String email;
private String password;
private String birthDate;
private String gender;
private String postalCode;
private int active;
public Long getIdUser() {
return idUser;
}
public void setIdUser(Long idUser) {
this.idUser = idUser;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getAvatarResource() {
return avatarResource;
}
public void setAvatarResource(String avatarResource) {
this.avatarResource = avatarResource;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public Long getId() {
return idUser;
}
public void setId(Long idUser) {
this.idUser = idUser;
}
public int getActive() {
return active;
}
public void setActive(int active) {
this.active = active;
}
/* Relations */
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Comment> comments;
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<UserMemory> userMemories;
public List<UserMemory> getUserMemories() {
return userMemories;
}
public void setUserMemories(List<UserMemory> userMemories) {
this.userMemories = userMemories;
}
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Vote> votes;
public List<Vote> getVotes() {
return votes;
}
public void setVotes(List<Vote> votes) {
this.votes = votes;
}
#OneToMany(mappedBy = "userFollower", fetch = FetchType.LAZY)
private List<Follow> usersFollowers;
public List<Follow> getUsersFollowers() {
return usersFollowers;
}
public void setUsersFollowers(List<Follow> usersFollowers) {
this.usersFollowers = usersFollowers;
}
#OneToMany(mappedBy = "userFollowing", fetch = FetchType.LAZY)
private List<Follow> usersFollowing;
public List<Follow> getUsersFollowing() {
return usersFollowing;
}
public void setUsersFollowing(List<Follow> usersFollowing) {
this.usersFollowing = usersFollowing;
}
}
By having fetchtype.LAZY, some of the values won't exist during serialization. This will make the ObjectMapper to try to fetch these and it all will end up in some kind of infinite loop.
It is never recommended to serialize #Entity annotated classes because database tables can change and that in turn will change the API for the calling clients.
Best way is to have specific ResponseDTOs that you transfer your data to before serialization so that the API and the database tables can change without breaking anything.
So, the problem was that in the backend I was using the writeValueAsString of the ObjectMapper class like this.
public Object register(#RequestBody String json){
User user = new User();
user.set...
...
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(user);
}
For some reason the writeValueAsString method gives a StackOverFlowException for a recursive behavior when there is a relationship into the database, this is a problem related with JPA or Hibernate, I am not sure about which one of those.
The solution was to write my own method to build a JSONObject with the information of my POJO:
public String buildUserJSON(User user) {
JSONObject userJson = new JSONObject();
userJson.put("idUser", user.getIdUser());
...
return userJson.toString();
}
And then call this method in my RestController to build the JSON that I want to return. As I said I do not know what was the problem but at least this was the solution for me.
Note: I found the solution to this be cause in the past I was with a problem similar like this one but when I was trying to return a List<T> as a JSON, so, I though that was related with the same thing.
Regards.
The problem was with Jackson, so to get out of this problem you most use two annotations in the relations of your entities.
More information, please see the next link: Here is the answer
Hope it can help for anyone.
I am using spring/jpa for a project, and I have an entity which has an #OneToMany annotation on a List.The other entity has an #ManyToOne annotation. Although when I retrieve the parent entity by its id, the size of the returned List (child entity) is always 0
Text version of test
#Test
public void createReccomendation() throws ServiceException, FileNotFoundException, UserDoesNotExistException, UserNameIsNotUniqueException, IllegalUserNameException {
String uid = UUID.randomUUID().toString();
Employee employee = employeeService.createEmployee("hi", uid+"#me.com", uid, "secret password", 23.234, 23.23, "image", "23dAD", "seattle", "usa");
List<String> images = new ArrayList<>();
String image1 = "image1/url";
String image2 = "image2/url";
String image3 = "image3/url";
images.add(image1);
images.add(image2);
images.add(image3);
Employee e = employeeService.getEmployeeById(employee.getId());
Recommendation rec = recommendationService.createRecommendation(e.getId(), "title", "Description", 23.23, 23.23, "persikogatan", "stockholm", "Sweden", images);
Recommendation rec2 = recommendationService.getRecommendationById(rec.getId());
Assert.assertEquals(rec.getTitle(), "title");
Assert.assertEquals(rec.getRecommendationimages().get(0).getPath(), image1);
Assert.assertEquals(3, rec2.getRecommendationimages().size());
}
This parent entity
#Entity
#Table(name = "recommendation")
public class Recommendation extends BusinessEntity {
#ManyToOne
#JoinColumn(name = "employeeid")
private Employee employee;
#OneToMany(mappedBy = "recommendation", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
List<RecommendationImage> recommendationimages;
public Recommendation() {}
public Recommendation(Employee employee, String title, String description, double targetLat, double targetLong,
String street, String city, String country, List<RecommendationImage> images
) {
this.employee = employee;
this.title = title;
this.description = description;
this.targetLat = targetLat;
this.targetLong = targetLong;
this.street = street;
this.city = city;
this.country = country;
this.active = true;
this.recommendationimages = images;
}
And this child entity
#Entity
#Table(name = "recommendationimage")
public class RecommendationImage extends ImageEntity{
#ManyToOne
private Recommendation recommendation;
Super class of child entity
#MappedSuperclass
public abstract class ImageEntity extends BaseEntity{
#Column(name="path", length=700)
String path;
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
RecommendationService class
#Service
public class RecommendationService{
private static final Logger log = LogManager.getLogger(DealService.class);
#Autowired
RecommendationRepository recommendationRepository;
public Recommendation getRecommendationById(Long id){
return recommendationRepository.findOne(id);
}
}
public List<RecommendationImage> translateToRecommendationImages(List<String> rawImages) throws ServiceException {
try{
List<RecommendationImage> recommendationImages = new ArrayList<>();
for(String image: rawImages){
RecommendationImage newImage = new RecommendationImage(image);
recommendationImages.add(newImage);
}
return recommendationImages;
}catch(Exception e){
log.warn("** SERVICE EXCEPTION ** FOR METHOD: translateRecommendationImages()");
throw new ServiceException("Could not translate raw images to RecommendationImage", e);
}
}
public Recommendation createRecommendation(Long employeeId, String title, String description, double targetLat,
double targetLong, String street, String city, String country,
List<String> rawImages) throws ServiceException {
log.info("createRecommendation(): employeeId: "+employeeId+" recommendationTitle: "+title);
Employee employee=null;
Recommendation rec=null;
String imagepath=null;
try {
List<RecommendationImage> images = translateToRecommendationImages(rawImages);
employee = employeeRepository.getEmployeeByid(employeeId);
rec = new Recommendation(employee, title, description, targetLat, targetLong, street, city, country, images);
// Recommendation rec2 = CheckProximity.getRecommendationProximity(rec, employee);
return recommendationRepository.save(rec);
}catch(Exception e){
log.warn("** SERVICE EXCEPTION ** FOR METHOD: createRecommendation(): employeeId: "+employeeId);
e.printStackTrace();
throw new ServiceException("Could not create recommendation at this time: "+rec.toString(), e);
}
}
Any help would be appreciated thanks!
Nowhere in your supplied code to you actually populate the list of RecommendationImages. So I'm going to guess.
When dealing with bidirectional relationships, in order for them to be persisted, the side of the relationship without the mappedBy needs to be updated. I'm guessing that you add RecommendationImages to your Recommendation, without setting the Recommendation of your RecommendationImages.
Typically, you would need a method like this:
public class Recommendation {
//...
private List<RecommendationImage> images = new ArrayList<>();
public void addRecommendationImage(final RecommendationImage newImage) {
recommendationImages.add(newImage);
newImage.setRecommendation(this);
}
}
Update: With the new code supplied it seems my guess was correct. Make the changes above, and then change the for-loop in translateToRecommendationImages to this:
public List<RecommendationImage> translateToRecommendationImages(Recommendation recommendation, List<String> rawImages) throws ServiceException {
//try and whatnot
for(String image: rawImages){
recommendation.addRecommendationImage(new RecommendationImage(image));
}
I am trying to create a springboot usermanagement application.
I have an entity object which contains two blob elements.Here is my entity object.
#Entity
#Table(name="user_meta_profile")
public class UserMetaProfile implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "user_id")
private int user_id;
#Column(name = "resume_file")
#Lob
private Blob resume_file;
#Column(name = "photo")
#Lob
private Blob photo;
#Column(name = "username")
private String username;
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
public Blob getResume_file() {
return resume_file;
}
public void setResume_file(Blob resume_file) {
this.resume_file = resume_file;
}
public Blob getPhoto() {
return photo;
}
public void setPhoto(Blob photo) {
this.photo = photo;
}
public void setUsername(String username) {
this.username = username;
}
}
As you can see there are two blob items 'resume_file' and 'photo'.
I want to send back a JSON response to the API call.
My Controller code is as shown below.
#Controller
#RequestMapping("/v1")
public class UsersController {
#Autowired
private IUserMetaProfileService userMetaProfileService;
#GetMapping("MetaProfile/{id}")
public ResponseEntity<UserMetaProfile> getUserMetaProfileById(#PathVariable("id") Integer id) {
UserMetaProfile userMetaProfile = userMetaProfileService.getUsersById(id);
return new ResponseEntity<UserMetaProfile>(userMetaProfile, HttpStatus.OK);
}
}
But when I call the API, I get the exception:
"exception": "org.springframework.http.converter.HttpMessageNotWritableException",
"message": "Could not write JSON document: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain:
...
...nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
Since JSON cannot contain binary data you need to serialize those fields as something else. You have a couple of options:
If you intend to show the binary as an image (since yours is a photo) you can serialize it as a data uri.
Send links to photos instead and create a controller method that will output the binary data with the appropriate content type (beyond the scope here).
So for Option 1 you can do something like this:
#Entity
#Table(name="user_meta_profile")
public class UserMetaProfile implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "user_id")
private int user_id;
#Column(name = "resume_file")
#Lob
private Blob resume_file;
#Column(name = "photo")
#Lob
private Blob photo;
#Column(name = "username")
private String username;
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
#JsonIgnore // disable serializing this field by default
public Blob getResume_file() {
return resume_file;
}
// serialize as data uri insted
#JsonProperty("resumeData")
public String getResume() {
// just assuming it is a word document. you would need to cater for different media types
return "data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64," + new String(Base64.getEncoder().encode(resume_file.getBytes()));
}
public void setResume_file(Blob resume_file) {
this.resume_file = resume_file;
}
#JsonIgnore // disable this one too
public Blob getPhoto() {
return photo;
}
// serialize as data uri instead
#JsonProperty("photoData")
public String getPhotoBase64() {
// just assuming it is a jpeg. you would need to cater for different media types
return "data:image/jpeg;base64," + new String(Base64.getEncoder().encode(photo.getBytes()));
}
public void setPhoto(Blob photo) {
this.photo = photo;
}
public void setUsername(String username) {
this.username = username;
}
}
For the photo bit the value of the photoData JSON attribute can be set directly as the src attribute of an img tag and the photo will be rendered in the HTML. With the resume file you can attach it as an href to a <a> tag with a download attribute so it can be downloaded:
<a href={photoData value here} download>Download Resume File</a>
Just as an FYI if the files are large the JSON will be huge and it might also slow down the browser.
I have written a spring boot web/rest application to handle a legacy system (DB tables), this application does the following:
user create a bill request through a REST WS.
My rest app store the request to Legacy DB Tables.
another system(X) (out my control) reads the record and generate a zip file.
X system then store the file in our table (zip file and file name).
user can now download the file using my application.
the issue here some bill files are large (1-2 GB) and I'm getting:
java.lang.OutOfMemoryError: Java heap space
this happens in Hibernate when I'm trying to select the file content
now how can I let the user download a large file without getting above error? please check below for POJO classes and Repos
Entity Class
#Entity
public class EbillStatus implements Serializable {
private static final long serialVersionUID = 1L;
#Id #GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy="uuid")
#Column(name="EBILL_STATUS_ID")
private String id;
#Column(name="CORPORATE_EBILL_ID", insertable=false, updatable=false)
private String corporateEbillId;
#Temporal(TemporalType.TIMESTAMP)
#Column(name="COMPLETION_DATETIME")
private Date completionDatetime;
#Column(name="FILENAME", insertable=false, updatable=false)
private String filename;
#Lob
private byte[] fileContent;
#Column(name="USER_ID")
private String username;
#Column(name="STATUS_ID")
private Integer status;
#Column(name="BILL_COUNT", insertable=false, updatable=false)
private Integer billCount;
private Integer accountCount;
}
The Repository:
public interface EbillStatusRepository extends JpaRepository<EbillStatus, String> {
EbillStatus findByCorporateEbill(CorporateEbill corporateEbill);
#Query(value="select s FROM EbillStatus s WHERE s.corporateEbillId=?1")
EbillStatus findFile(String corporateEbillId);
}
Service Method Implementation:
#Service
public class EbillServiceImpl implements EbillService {
private EbillStatusRepository statusRepo;
#Autowired
public EbillServiceImpl(EbillStatusRepository statusRepo){
this.statusRepo = statusRepo;
}
#Override
public EbillFileModel getEbillFile(String username, String eBillId) throws NotFoundException{
EbillStatus ebill= statusRepo.findFile(eBillId);
if(ebill == null || !isEbillFileAvailable(ebill.getStatus()))
throw new NotFoundException("file not available for username: "+username+", eBillId: "+ eBillId);
return new EbillFileModel(ebill.getFilename(), ebill.getFileContent());
}
private boolean isEbillFileAvailable(Integer status){
return COMPLETED.equals(String.valueOf(status)) || DELIVERED.equals(String.valueOf(status));
}
}
Pojo Class which is given to the controller
public class EbillFileModel {
private String fileName;
private byte[] fileContent;
public EbillFileModel(String fileName, byte[] fileContent) {
super();
this.fileName = fileName;
this.fileContent = fileContent;
}
public EbillFileModel() {
super();
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public byte[] getFileContent() {
return fileContent;
}
public void setFileContent(byte[] fileContent) {
this.fileContent = fileContent;
}
}
Controller method to Download the file
#GetMapping(value = "/{username}/order/{eBillId}/download", produces = "application/zip")
public ResponseEntity<ByteArrayResource> downloadEbillFile(#PathVariable String username, #PathVariable String eBillId)
throws IOException, NotFoundException {
EbillFileModel file = ebillservice.getEbillFile(username, eBillId);
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CACHE_CONTROL, CACHE_CONTROL_VAL);
headers.add(HttpHeaders.PRAGMA,PRAGMA_VAL);
headers.setContentDispositionFormData(ATTACHMENT, file.getFileName());
headers.add(HttpHeaders.EXPIRES, ZERO);
return ResponseEntity
.ok()
.headers(headers)
.contentType(APPLICATION_ZIP)
.body(new ByteArrayResource(file.getFileContent()));
}
Summary and Notes:
I cannot change the system design and how it works, I just wrote a Web/REST application on top of it.
I'm using Spring boot 1.5.1.RELEASE and java 8
the packaging is a WAR file deployed on JBoss EAP 7
what is the best way to download large files stored in DB.