Java tutorial
/** * This file is part of alf.io. * * alf.io is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * alf.io is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with alf.io. If not, see <http://www.gnu.org/licenses/>. */ package alfio.manager; import alfio.model.FileBlobMetadata; import alfio.model.modification.UploadBase64FileModification; import alfio.repository.FileUploadRepository; import alfio.util.Json; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import lombok.extern.log4j.Log4j2; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.support.AbstractLobCreatingPreparedStatementCallback; import org.springframework.jdbc.support.lob.DefaultLobHandler; import org.springframework.jdbc.support.lob.LobCreator; import org.springframework.jdbc.support.lob.LobHandler; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StreamUtils; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.*; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.*; import java.util.concurrent.TimeUnit; @Component @Transactional @Log4j2 public class FileUploadManager { private final NamedParameterJdbcTemplate jdbc; private final FileUploadRepository repository; private final Cache<String, byte[]> cache = Caffeine.newBuilder().maximumSize(20) .expireAfterWrite(20, TimeUnit.MINUTES).build(); @Autowired public FileUploadManager(NamedParameterJdbcTemplate jdbc, FileUploadRepository repository) { this.jdbc = jdbc; this.repository = repository; } public Optional<FileBlobMetadata> findMetadata(String id) { return repository.findById(id); } public void outputFile(String id, OutputStream out) { byte[] res = cache.get(id, identifier -> { ByteArrayOutputStream baos = new ByteArrayOutputStream(); SqlParameterSource param = new MapSqlParameterSource("id", id); jdbc.query(repository.fileContent(id), param, rs -> { try (InputStream is = rs.getBinaryStream("content")) { StreamUtils.copy(is, baos); } catch (IOException e) { throw new IllegalStateException("Error while copying data", e); } }); return baos.toByteArray(); }); try { StreamUtils.copy(res, out); } catch (IOException e) { throw new IllegalStateException("Error while copying data", e); } } public String insertFile(UploadBase64FileModification file) { String digest = DigestUtils.sha256Hex(file.getFile()); if (Integer.valueOf(1).equals(repository.isPresent(digest))) { return digest; } LobHandler lobHandler = new DefaultLobHandler(); jdbc.getJdbcOperations().execute(repository.uploadTemplate(), new AbstractLobCreatingPreparedStatementCallback(lobHandler) { @Override protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException { ps.setString(1, digest); ps.setString(2, file.getName()); ps.setLong(3, file.getFile().length); lobCreator.setBlobAsBytes(ps, 4, file.getFile()); ps.setString(5, file.getType()); ps.setString(6, Json.GSON.toJson(getAttributes(file))); } }); return digest; } public void cleanupUnreferencedBlobFiles() { int deleted = repository.cleanupUnreferencedBlobFiles(DateUtils.addDays(new Date(), -1)); log.debug("removed {} unused file_blob", deleted); } private Map<String, String> getAttributes(UploadBase64FileModification file) { if (!StringUtils.startsWith(file.getType(), "image/")) { return Collections.emptyMap(); } try { BufferedImage image = ImageIO.read(new ByteArrayInputStream(file.getFile())); Map<String, String> attributes = new HashMap<>(); attributes.put(FileBlobMetadata.ATTR_IMG_WIDTH, String.valueOf(image.getWidth())); attributes.put(FileBlobMetadata.ATTR_IMG_HEIGHT, String.valueOf(image.getHeight())); return attributes; } catch (IOException e) { log.error("error while processing image: ", e); return Collections.emptyMap(); } } }