在对 BLOB 发出 GET 请求时,HttpServletResponse 如何与 fetch API 纠缠在一起?

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

使用 Spring 启动,我正在尝试实现一个 REST 控制器,它可以处理一个 GET 请求,请求从我的数据库中 return 一个 BLOB 对象。

谷歌搜索了一下,并将各个部分放在一起,我创建了以下代码片段:

@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();
    }
}

我正在使用 VanillaJS 和 fetch-API:

发送 GET 请求
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);
  } 
}

不知何故,这行得通。太好了,但是现在我想了解 HttpServletResponse 在这种情况下的用法,我并不熟悉。在我看来,fetch-API 使用了 HttpServletResponse(甚至可能创建它),因为我没有创建这个对象或对它做任何事情。

令我感到非常奇怪的是,我的控制器方法 getProfilePicture() 的 return 类型是 void,但我仍在发送响应,这绝对不是无效。

此外,如果在我的数据库中找不到 profilePicture,例如由于传递了一个不存在的 studentId,我的控制器方法不会执行任何操作。但是,我仍然收到 200 的响应代码。这就是为什么我在我的 Javascript 中添加了 responseBlob.size > 0 部分以检查是否有肯定响应。

有人能给我解释一下这个魔法吗?

response.getOutputStream(); javadoc 说“Returns a ServletOutputStream 适合在响应中写入二进制数据。”它实际上是响应流,您将图片字节写入其中。它与客户端阅读响应无关。或者你可以 return 一个字节数组,它会自动写入响应流,结果是一样的。

要 return 不同的 http 状态代码,您应该将方法 return 类型更改为 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 基本上是 return 不同状态 codes/messages.

的弹簧方式

您通过 javascript 手动下载图像是否有原因?您可以只创建一个带有 http link 的 img 元素到图像,浏览器将自动显示图像内容:<img src="http://localhost:8080/student/pic/studentId">