Rendering images
Previously, viewing an image would only display the size of the
binary file in bytes. This change allows common-typed images to
be rendered in browser using MimeTypes for type checking.
Github issue: https://github.com/google/gitiles/issues/136
Change-Id: I7d987962d6632571578af7b66db53945f219eb80
diff --git a/java/com/google/gitiles/BlobSoyData.java b/java/com/google/gitiles/BlobSoyData.java
index e898101..7e96d65 100644
--- a/java/com/google/gitiles/BlobSoyData.java
+++ b/java/com/google/gitiles/BlobSoyData.java
@@ -20,7 +20,9 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
+import com.google.common.io.BaseEncoding;
import com.google.template.soy.data.SoyListData;
import com.google.template.soy.data.SoyMapData;
import java.io.IOException;
@@ -57,6 +59,11 @@
*/
private static final int MAX_LINE_COUNT = 50000;
+ /** Allowed image extensions to render */
+ private static final ImmutableSet<String> ALLOWED_IMAGE_TYPES =
+ ImmutableSet.of(
+ "image/gif", "image/jpeg", "image/jpg", "image/png", "image/tiff", "image/webp");
+
private final GitilesView view;
private final ObjectReader reader;
@@ -76,8 +83,16 @@
ObjectLoader loader = reader.open(blobId, Constants.OBJ_BLOB);
String content;
+ String imageBlob;
try {
byte[] raw = loader.getCachedBytes(MAX_FILE_SIZE);
+
+ String type = MimeTypes.getMimeType(path);
+ if (ALLOWED_IMAGE_TYPES.contains(type) && raw.length < MAX_FILE_SIZE) {
+ imageBlob = "data:" + type + ";base64," + BaseEncoding.base64().encode(raw);
+ } else {
+ imageBlob = null;
+ }
content =
(raw.length < MAX_FILE_SIZE && !RawText.isBinary(raw)) ? RawParseUtils.decode(raw) : null;
if (isContentTooLargeForDisplay(content)) {
@@ -87,6 +102,7 @@
throw e;
} catch (LargeObjectException e) {
content = null;
+ imageBlob = null;
}
if (content != null) {
@@ -102,6 +118,9 @@
data.put("fileUrl", GitilesView.path().copyFrom(view).toUrl());
data.put("logUrl", GitilesView.log().copyFrom(view).toUrl());
data.put("blameUrl", GitilesView.blame().copyFrom(view).toUrl());
+ if (imageBlob != null) {
+ data.put("imgBlob", imageBlob);
+ }
}
return data;
}
diff --git a/resources/com/google/gitiles/templates/ObjectDetail.soy b/resources/com/google/gitiles/templates/ObjectDetail.soy
index 054f621..5e5a3a8 100644
--- a/resources/com/google/gitiles/templates/ObjectDetail.soy
+++ b/resources/com/google/gitiles/templates/ObjectDetail.soy
@@ -257,6 +257,7 @@
{template blobDetail}
{@param sha: ?} /** SHA of this file's blob. */
{@param? logUrl: ?} /** optional URL to a log for this file. */
+ {@param? imgBlob: ?} /** optional image blob to render. */
{@param? blameUrl: ?} /** optional URL to a blame for this file. */
{@param lines: ?} /** lines (may be empty), or null for a binary file. Each line is a list of
entries with "classes" and "text" fields for pretty-printed spans. */
@@ -292,7 +293,11 @@
{/if}
{else}
<div class="FileContents-binary">
- {msg desc="size of binary file in bytes"}{$size}-byte binary file{/msg}
+ {if $imgBlob}
+ <img src="{$imgBlob}"/>
+ {else}
+ {msg desc="size of binary file in bytes"}{$size}-byte binary file{/msg}
+ {/if}
</div>
{/if}
{/template}