返回图片
下面的文档将介绍在 tio-boot 框架中,如何在 Controller 中返回图片给浏览器,包括生成验证码图片、二维码图片以及与 Next.js 配合返回图片的完整示例。
1. 返回验证码图片
利用 Hutool 库生成并返回图形验证码。此示例通过 LineCaptcha 来生成带有干扰线的图形验证码,并以 JPEG 图片的形式返回给前端。
1.1 代码示例
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import com.litongjava.annotation.AController;
import com.litongjava.annotation.RequestPath;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.util.Resps;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
@RequestPath("/captcha")
public class CaptchaController {
@RequestPath("")
public HttpResponse captcha(HttpRequest request) {
// 创建线性验证码,尺寸为 200x100
LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 100);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
// 将验证码图片写入输出流
captcha.write(outputStream);
// 将输出流转换为字节数组
byte[] captchaBytes = outputStream.toByteArray();
// 使用 Resps 工具类创建包含验证码图片的响应
HttpResponse response = Resps.bytesWithContentType(request, captchaBytes, "image/jpeg");
// 返回响应
return response;
} catch (IOException e) {
e.printStackTrace();
return Resps.json(request, RespBodyVo.fail("Error generating captcha"));
}
}
}
1.2 代码解析
依赖与导包
import cn.hutool.captcha.LineCaptcha;
:来自 Hutool 库的验证码生成类。import com.litongjava.tio.http.server.util.Resps;
:tio-boot 提供的工具类,用于快速创建各种响应类型。
路由定义
@RequestPath("/captcha")
:类级别的注解,表示当请求路径以/captcha
为前缀时,交由该类处理。@RequestPath("")
:方法级别的注解,处理具体的请求路径/captcha
(此处等同于"/captcha"
)。
生成并返回验证码
LineCaptcha captcha = CaptchaUtil.createLineCaptcha(200, 100);
:生成 200×100 大小的验证码图片。captcha.write(outputStream);
:将验证码写入到内存的ByteArrayOutputStream
。Resps.bytesWithContentType(request, captchaBytes, "image/jpeg")
:将字节数组作为图片响应返回,并指定其 Content-Type 为image/jpeg
。
异常处理
- 若捕获到
IOException
,则返回一个包含错误信息的 JSON 响应。
- 若捕获到
2. 返回二维码图片
2.1 Maven 依赖
若需使用 ZXing 核心库,需要在 pom.xml
中添加以下依赖:
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
2.2 代码示例
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import com.litongjava.annotation.RequestPath;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.util.Resps;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
@RequestPath("/qr")
public class QrController {
@RequestPath("")
public HttpResponse qr(HttpRequest request, String content) {
// 获取要生成的二维码内容
if (StrUtil.isBlank(content)) {
return Resps.json(request, RespBodyVo.fail("No content provided for QR code"));
}
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
// 生成二维码图片,并写入到输出流(300×300 像素,PNG 格式)
QrCodeUtil.generate(content, 300, 300, "png", outputStream);
// 将输出流转换为字节数组
byte[] qrCodeBytes = outputStream.toByteArray();
// 使用 Resps 工具类创建一个包含二维码图片的响应
HttpResponse response = Resps.bytesWithContentType(request, qrCodeBytes, "image/png");
// 返回响应
return response;
} catch (IOException e) {
e.printStackTrace();
return Resps.json(request, RespBodyVo.fail("Error generating QR code"));
}
}
}
2.3 代码解析
依赖与导包
QrCodeUtil
来自 Hutool 提供的二维码工具类,需要依赖 ZXing 进行二维码生成。
路由定义
@RequestPath("/qr")
:类级别注解,处理以/qr
开头的请求。
获取参数并生成二维码
- 通过方法签名中的
String content
获取前端传入的二维码内容。 - 使用
QrCodeUtil.generate(content, 300, 300, "png", outputStream)
方法生成二维码,并输出到ByteArrayOutputStream
。
- 通过方法签名中的
创建响应并返回
Resps.bytesWithContentType(request, qrCodeBytes, "image/png")
:封装生成的二维码字节码为 PNG 格式并返回。- 若
content
为空或二维码生成出错,则返回相应的 JSON 格式错误信息。
2.4 请求示例
GET http://localhost/qr?content=tio-boot
上述请求将生成包含文本 “tio-boot” 的二维码图片。
3. 与 Next.js 配合返回图片
以下示例展示了如何处理 Next.js 向后端请求图片的场景,尤其在使用 _next/image
API 时,需要根据请求参数解析并返回对应的图片文件。
3.1 代码示例
package com.litongjava.admin.controller;
import java.io.File;
import com.litongjava.annotation.Get;
import com.litongjava.annotation.RequestPath;
import com.litongjava.tio.boot.http.TioRequestContext;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.server.util.Resps;
import com.litongjava.tio.utils.hutool.FileUtil;
import com.litongjava.tio.utils.hutool.FilenameUtils;
import com.litongjava.tio.utils.url.UrlUtils;
@RequestPath("/_next")
public class NextImageController {
String staticFileFolder = "blog-ui/";
// 示例:/_next/image?url=%2Fstatic%2Fimages%2Fnicolaus-avatar.png&w=48&q=75
@Get("/image")
public HttpResponse image(String url, int w, int q) {
HttpResponse response = TioRequestContext.getResponse();
// 1. 对 url 进行解码
url = UrlUtils.decode(url);
// 2. 获取文件后缀作为返回类型
String suffix = FilenameUtils.getSuffix(url);
// 3. 构造图片文件路径
File file = new File(staticFileFolder + url);
if (file.exists()) {
// 读取文件内容
byte[] readBytes = FileUtil.readBytes(file);
// 指定图片的 contentType
Resps.bytesWithContentType(response, readBytes, "image/" + suffix);
return response;
} else {
// 文件不存在,返回 404
return response.setStatus(404);
}
}
}
3.2 代码解析
路由定义
@RequestPath("/_next")
:类级别注解,表示处理/_next
开头的请求。@Get("/image")
:方法级别注解,处理GET /_next/image
请求。
处理图片请求
String url, int w, int q
:方法参数分别对应请求中的url、w、q
参数。例如url=%2Fstatic%2Fimages%2Fnicolaus-avatar.png
。UrlUtils.decode(url)
:对路径进行 URL 解码。- 使用
FilenameUtils.getSuffix(url)
获取文件后缀,以便设置正确的响应 Content-Type。 - 若文件存在,读取文件字节数组,并以
image/[suffix]
的形式返回;否则返回404
。
前端请求示例
GET http://localhost/_next/image?url=%2Fstatic%2Fimages%2Fnicolaus-avatar.png&w=48&q=75
该请求会在服务器指定的目录 blog-ui/
下寻找 static/images/nicolaus-avatar.png
文件,并将其以图片形式返回给浏览器。
4. 总结
在 tio-boot 中返回图片的核心思路主要如下:
获取或生成图片:
- 验证码、二维码等可使用 Hutool 库来生成。
- 直接读取本地或网络文件,也可用
File
、FileUtil
等工具类来操作。
输出为字节流:
- 将生成或读取到的图片转换为
byte[]
数组。
- 将生成或读取到的图片转换为
设置合适的 Content-Type:
- 对于验证码或普通图片可设置
image/jpeg
、image/png
等。 - 对于 SVG 等矢量格式可设置
image/svg+xml
。
- 对于验证码或普通图片可设置
返回响应:
- 使用
Resps.bytesWithContentType()
将字节数组和对应的 Content-Type 打包成可识别的 HttpResponse。 - 若出现异常或者文件不存在,则返回相应的错误信息或 404 状态码。
- 使用
通过以上示例,可以轻松地在 tio-boot 环境中生成并返回验证码、二维码等各类图片。结合 Next.js 等前端框架时,只需根据请求参数解析目标文件路径并返回即可,从而实现前后端的无缝衔接。