Home > database >  How is HttpServletResponse entangled with the fetch API when making a GET request for a BLOB?
How is HttpServletResponse entangled with the fetch API when making a GET request for a BLOB?

Time:01-05

Using Spring Boot, I am trying to implement a REST controller, which can handle a GET request asking to return a BLOB object from my database.

Googling around a little bit, and putting pieces together, I have created the following code snippet:

@GetMapping("student/pic/studentId")
public void getProfilePicture(@PathVariable Long studentId, HttpServletResponse response) throws IOException {
    Optional<ProfilePicture> profilePicture;
    profilePicture = profilePictureService.getProfilePictureByStudentId(studentId);
    if (profilePicture.isPresent()) {
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(profilePicture.get().getPicture());
        outputStream.close();
    }
}

I am sending the GET request using VanillaJS and the fetch-API:

async function downloadPicture(profilePic, studentId) {
  const url = "http://localhost:8080/student/pic/"   studentId;
  const response = await fetch(url);
  const responseBlob = await response.blob();
  if (responseBlob.size > 0) {
    profilePic.src = URL.createObjectURL(responseBlob);
  } 
}

Somehow, this works. That's great, but now I would like to understand the usage of HttpServletResponse in this context, which I am not familiar with. It seems to me that the fetch-API makes use of HttpServletResponse (maybe even creates it), since I am not creating this object or do anything with it.

What is very strange to me is that the return-type of my controller method getProfilePicture() is void, and still I am sending a response, which is most definitely not void.

Also, if the profilePicture was not found in my database, for example due to a non-existing studentId being passed, my controller-method does not do anything. But still, I am getting a response code of 200. That's why I have added the responseBlob.size > 0 part in my Javascript to check for a positive response.

Can someone explain this magic to me, please?

CodePudding user response:

response.getOutputStream(); javadoc says "Returns a ServletOutputStream suitable for writing binary data in the response." It's literally the response stream and you write the picture bytes into it. It's not related to the client reading the response. Alternatively you could just return a byte array which will be automatically written into the response stream and the result will be the same.

To return a different http status code you should change the method return type to ResponseEntity<byte[]>:

@GetMapping("student/pic/studentId")
public ResponseEntity<byte[]> getProfilePicture(@PathVariable Long studentId, HttpServletResponse response) throws IOException {
    Optional<ProfilePicture> profilePicture = profilePictureService.getProfilePictureByStudentId(studentId);
    if (profilePicture.isPresent()) {
        return ResponseEntity.ok(profilePicture.get().getPicture()); //status code 200
    } else {
        return ResponseEntity.notFound().build(); //status code 404
    }
}

ResponseEntity is basically springs way to return different status codes/messages.

Is there a reason why you are manually downloading the image via javascript? You could just create a img element with the http link to the image and the browser will automatically display the image content: <img src="http://localhost:8080/student/pic/studentId">

  •  Tags:  
  • Related