无法将Telegram Bot接收到的照片以字节数组形式存入数据库
Java Telegram Bot 接收照片转字节数组存入数据库实现方案
核心实现步骤
1. 优化照片尺寸选择
你当前代码直接取photo.get(0)获取的是最低分辨率的照片,建议优先取最大分辨率的版本:
// 取分辨率最高的照片 PhotoSize largestPhoto = update.getMessage().getPhoto().stream() .max(Comparator.comparing(PhotoSize::getFileSize)) .orElseThrow(() -> new RuntimeException("未获取到有效照片")); GetFile getFile = new GetFile(); getFile.setFileId(largestPhoto.getFileId());
2. 下载文件并转为字节数组
使用try-with-resources自动关闭流,避免资源泄漏,有两种常用实现方式:
方式1:JDK原生实现(无需额外依赖)
byte[] photoBytes; try (InputStream inputStream = new FileInputStream(getFileRequest(getFile))) { photoBytes = inputStream.readAllBytes(); // JDK 9+ 支持 } catch (IOException e) { // 自定义异常处理逻辑,比如记录日志、回复用户上传失败 throw new RuntimeException("照片读取失败", e); }
如果是JDK 8版本,替换readAllBytes的逻辑:
ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[1024]; try (InputStream inputStream = new FileInputStream(getFileRequest(getFile))) { while ((nRead = inputStream.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); photoBytes = buffer.toByteArray(); } catch (IOException e) { throw new RuntimeException("照片读取失败", e); }
方式2:使用Apache Commons IO工具类(需要引入依赖)
<!-- pom.xml 引入依赖 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.15.1</version> </dependency>
转字节数组代码:
byte[] photoBytes; try (InputStream inputStream = new FileInputStream(getFileRequest(getFile))) { photoBytes = IOUtils.toByteArray(inputStream); } catch (IOException e) { throw new RuntimeException("照片读取失败", e); }
3. 字节数组存入数据库
- 数据库字段选择:MySQL建议使用
MEDIUMBLOB(最大支持16MB)或LONGBLOB(最大支持4GB),避免普通BLOB最大64KB的限制存不下高清照片 - JDBC存入示例:
// 假设表结构为 CREATE TABLE tg_photos (chat_id BIGINT, photo BLOB, upload_time DATETIME) String sql = "INSERT INTO tg_photos(chat_id, photo, upload_time) VALUES (?, ?, NOW())"; try (PreparedStatement pstmt = connection.prepareStatement(sql)) { pstmt.setLong(1, chatId); pstmt.setBytes(2, photoBytes); pstmt.executeUpdate(); } catch (SQLException e) { throw new RuntimeException("照片存入数据库失败", e); }
完整修正后的代码示例
public void onUpdateReceived(Update update) { this.responseText = "Kerakli bo'limni tanlang:"; if (update.hasMessage() && update.getMessage().hasPhoto()) { this.chatId = update.getMessage().getChatId(); SendMessage sendMessage = new SendMessage(); try { // 1. 取最大分辨率照片 PhotoSize largestPhoto = update.getMessage().getPhoto().stream() .max(Comparator.comparing(PhotoSize::getFileSize)) .orElseThrow(() -> new RuntimeException("无效照片")); // 2. 获取文件 GetFile getFile = new GetFile(); getFile.setFileId(largestPhoto.getFileId()); File file = getFileRequest(getFile); // 3. 转字节数组 byte[] photoBytes; try (InputStream inputStream = new FileInputStream(file)) { photoBytes = inputStream.readAllBytes(); } // 4. 存入数据库 String sql = "INSERT INTO tg_photos(chat_id, photo, upload_time) VALUES (?, ?, NOW())"; try (PreparedStatement pstmt = connection.prepareStatement(sql)) { pstmt.setLong(1, chatId); pstmt.setBytes(2, photoBytes); pstmt.executeUpdate(); } // 回复用户上传成功 sendMessage.setChatId(chatId); sendMessage.setText("照片上传成功"); execute(sendMessage); } catch (Exception e) { // 异常处理,回复用户失败 sendMessage.setChatId(chatId); sendMessage.setText("照片上传失败,请重试"); try { execute(sendMessage); } catch (TelegramApiException ex) { ex.printStackTrace(); } e.printStackTrace(); } } }
注意事项
- 若照片文件过大,建议先做压缩处理再存入数据库,降低存储成本
- 生产环境建议不要直接把文件存在数据库,可存到对象存储服务,数据库只存文件访问链接即可,性能更好
- 所有IO和数据库操作都要做好异常捕获处理,避免程序崩溃
内容的提问来源于stack exchange,提问作者Shahzodbek Pulatbekov
相关产品推荐
相关产品推荐

