Improve images update methods.
This commit is contained in:
parent
acc67a2077
commit
b7b889117a
@ -17,17 +17,21 @@ package org.thingsboard.server.service.install.update;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.HasImage;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageDataIterable;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.asset.AssetProfileDao;
|
||||
import org.thingsboard.server.dao.dashboard.DashboardDao;
|
||||
import org.thingsboard.server.dao.device.DeviceProfileDao;
|
||||
import org.thingsboard.server.dao.resource.ImageService;
|
||||
import org.thingsboard.server.dao.tenant.TenantDao;
|
||||
import org.thingsboard.server.dao.widget.WidgetTypeDao;
|
||||
import org.thingsboard.server.dao.widget.WidgetsBundleDao;
|
||||
|
||||
@ -41,6 +45,7 @@ public class ImagesUpdater {
|
||||
private final ImageService imageService;
|
||||
private final WidgetsBundleDao widgetsBundleDao;
|
||||
private final WidgetTypeDao widgetTypeDao;
|
||||
private final TenantDao tenantDao;
|
||||
private final DashboardDao dashboardDao;
|
||||
private final DeviceProfileDao deviceProfileDao;
|
||||
private final AssetProfileDao assetProfileDao;
|
||||
@ -59,8 +64,7 @@ public class ImagesUpdater {
|
||||
|
||||
public void updateDashboardsImages() {
|
||||
log.info("Updating dashboards images...");
|
||||
var dashboardsIds = new PageDataIterable<>(dashboardDao::findAllIds, 1024);
|
||||
updateImages(dashboardsIds, "dashboard", imageService::replaceBase64WithImageUrl, dashboardDao);
|
||||
updateImages("dashboard", dashboardDao::findIdsByTenantId, imageService::replaceBase64WithImageUrl, dashboardDao);
|
||||
}
|
||||
|
||||
public void createSystemImages(Dashboard defaultDashboard) {
|
||||
@ -108,11 +112,44 @@ public class ImagesUpdater {
|
||||
|
||||
private <E extends HasImage> void updateImages(Iterable<? extends EntityId> entitiesIds, String type,
|
||||
Function<E, Boolean> updater, Dao<E> dao) {
|
||||
int updatedCount = 0;
|
||||
int totalCount = 0;
|
||||
int updatedCount = 0;
|
||||
var counts = updateImages(entitiesIds, type, updater, dao, totalCount, updatedCount);
|
||||
totalCount = counts[0];
|
||||
updatedCount = counts[1];
|
||||
log.info("Updated {} {}s out of {}", updatedCount, type, totalCount);
|
||||
}
|
||||
|
||||
private <E extends HasImage> void updateImages(String type, BiFunction<TenantId, PageLink, PageData<? extends EntityId>> entityIdsByTenantId,
|
||||
Function<E, Boolean> updater, Dao<E> dao) {
|
||||
int tenantCount = 0;
|
||||
int totalCount = 0;
|
||||
int updatedCount = 0;
|
||||
var tenantIds = new PageDataIterable<>(tenantDao::findTenantsIds, 128);
|
||||
for (var tenantId : tenantIds) {
|
||||
tenantCount++;
|
||||
var entitiesIds = new PageDataIterable<>(link -> entityIdsByTenantId.apply(tenantId, link), 128);
|
||||
var counts = updateImages(entitiesIds, type, updater, dao, totalCount, updatedCount);
|
||||
totalCount = counts[0];
|
||||
updatedCount = counts[1];
|
||||
if (tenantCount % 100 == 0) {
|
||||
log.info("Update {}s images: processed {} tenants so far", type, tenantCount);
|
||||
}
|
||||
}
|
||||
log.info("Updated {} {}s out of {}", updatedCount, type, totalCount);
|
||||
}
|
||||
|
||||
private <E extends HasImage> int[] updateImages(Iterable<? extends EntityId> entitiesIds, String type,
|
||||
Function<E, Boolean> updater, Dao<E> dao, int totalCount, int updatedCount) {
|
||||
for (EntityId id : entitiesIds) {
|
||||
totalCount++;
|
||||
E entity = dao.findById(TenantId.SYS_TENANT_ID, id.getId());
|
||||
E entity;
|
||||
try {
|
||||
entity = dao.findById(TenantId.SYS_TENANT_ID, id.getId());
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to update {} images: error fetching {} by id [{}]: {}", type, type, id.getId(), StringUtils.abbreviate(e.toString(), 1000));
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
boolean updated = updater.apply(entity);
|
||||
if (updated) {
|
||||
@ -127,7 +164,7 @@ public class ImagesUpdater {
|
||||
log.info("Processed {} {}s so far", totalCount, type);
|
||||
}
|
||||
}
|
||||
log.info("Updated {} {}s out of {}", updatedCount, type, totalCount);
|
||||
return new int[]{totalCount, updatedCount};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ import org.apache.batik.transcoder.TranscoderInput;
|
||||
import org.apache.batik.transcoder.TranscoderOutput;
|
||||
import org.apache.batik.transcoder.image.PNGTranscoder;
|
||||
import org.apache.batik.util.XMLResourceDescriptor;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.springframework.util.MimeType;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
@ -69,13 +70,17 @@ public class ImageUtils {
|
||||
|
||||
public static ProcessedImage processImage(byte[] data, String mediaType, int thumbnailMaxDimension) throws Exception {
|
||||
if (mediaTypeToFileExtension(mediaType).equals("svg")) {
|
||||
return processSvgImage(data, mediaType, thumbnailMaxDimension);
|
||||
try {
|
||||
return processSvgImage(data, mediaType, thumbnailMaxDimension);
|
||||
} catch (Exception e) {
|
||||
if (log.isDebugEnabled()) { // printing stacktrace
|
||||
log.warn("Couldn't process SVG image, leaving preview as original image", e);
|
||||
} else {
|
||||
log.warn("Couldn't process SVG image, leaving preview as original image: {}", ExceptionUtils.getMessage(e));
|
||||
}
|
||||
return previewAsOriginalImage(data, mediaType);
|
||||
}
|
||||
}
|
||||
ProcessedImage image = new ProcessedImage();
|
||||
image.setMediaType(mediaType);
|
||||
image.setData(data);
|
||||
image.setSize(data.length);
|
||||
|
||||
BufferedImage bufferedImage = null;
|
||||
try {
|
||||
bufferedImage = ImageIO.read(new ByteArrayInputStream(data));
|
||||
@ -83,6 +88,8 @@ public class ImageUtils {
|
||||
}
|
||||
if (bufferedImage == null) { // means that media type is not supported by ImageIO; extracting width and height from metadata and leaving preview as original image
|
||||
Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(data));
|
||||
ProcessedImage image = previewAsOriginalImage(data, mediaType);
|
||||
String dirName = "Unknown";
|
||||
for (Directory dir : metadata.getDirectories()) {
|
||||
Tag widthTag = dir.getTags().stream()
|
||||
.filter(tag -> tag.getTagName().toLowerCase().contains("width"))
|
||||
@ -94,24 +101,22 @@ public class ImageUtils {
|
||||
continue;
|
||||
}
|
||||
int width = Integer.parseInt(dir.getObject(widthTag.getTagType()).toString());
|
||||
int height = Integer.parseInt(dir.getObject(widthTag.getTagType()).toString());
|
||||
int height = Integer.parseInt(dir.getObject(heightTag.getTagType()).toString());
|
||||
image.setWidth(width);
|
||||
image.setHeight(height);
|
||||
|
||||
ProcessedImage preview = new ProcessedImage();
|
||||
preview.setWidth(image.getWidth());
|
||||
preview.setHeight(image.getHeight());
|
||||
preview.setMediaType(mediaType);
|
||||
preview.setData(null);
|
||||
preview.setSize(data.length);
|
||||
image.setPreview(preview);
|
||||
log.warn("Couldn't process {} ({}) with ImageIO, leaving preview as original image", mediaType, dir.getName());
|
||||
return image;
|
||||
image.getPreview().setWidth(width);
|
||||
image.getPreview().setHeight(height);
|
||||
dirName = dir.getName();
|
||||
break;
|
||||
}
|
||||
log.warn("Image media type {} not supported", mediaType);
|
||||
throw new IllegalArgumentException("Media type " + mediaType + " not supported");
|
||||
log.warn("Couldn't process {} ({}) with ImageIO, leaving preview as original image", mediaType, dirName);
|
||||
return image;
|
||||
}
|
||||
|
||||
ProcessedImage image = new ProcessedImage();
|
||||
image.setMediaType(mediaType);
|
||||
image.setData(data);
|
||||
image.setSize(data.length);
|
||||
image.setWidth(bufferedImage.getWidth());
|
||||
image.setHeight(bufferedImage.getHeight());
|
||||
|
||||
@ -202,6 +207,23 @@ public class ImageUtils {
|
||||
return image;
|
||||
}
|
||||
|
||||
private static ProcessedImage previewAsOriginalImage(byte[] data, String mediaType) {
|
||||
ProcessedImage image = new ProcessedImage();
|
||||
image.setMediaType(mediaType);
|
||||
image.setData(data);
|
||||
image.setSize(data.length);
|
||||
image.setWidth(0);
|
||||
image.setHeight(0);
|
||||
ProcessedImage preview = new ProcessedImage();
|
||||
preview.setMediaType(mediaType);
|
||||
preview.setData(null);
|
||||
preview.setSize(data.length);
|
||||
preview.setWidth(0);
|
||||
preview.setHeight(0);
|
||||
image.setPreview(preview);
|
||||
return image;
|
||||
}
|
||||
|
||||
private static int[] getThumbnailDimensions(int originalWidth, int originalHeight, int maxDimension) {
|
||||
if (originalWidth <= maxDimension && originalHeight <= maxDimension) {
|
||||
return new int[]{originalWidth, originalHeight};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user