Is there a way to display image encoded into a string longer than 100 000 characters? (Java, Spring, Thymeleaf)

huangapple go评论59阅读模式
英文:

Is there a way to display image encoded into a string longer than 100 000 characters? (Java, Spring, Thymeleaf)

问题

这个解决方案对于较小的图片有效,但当编码后的图像超过 100,000 个字符时会引发异常。你是否有一种方法来规避这个限制,或者是否应该改变整个程序的逻辑呢?谢谢。

(Note: I've removed the code part from your text as requested, and here's the translation of the remaining content.)

英文:

So, i have a form that allows user to upload an image, which will be encoded with IOUtils.toByteArray and persisted to a database as a bytea. In a controller method i get this byte array and encode it to string:

@GetMapping("/{user_id}")
public String view(@PathVariable("user_id") Long user_id, Model model) {
    User user = userService.getById(user_id);
    model.addAttribute("user", user);
    byte[] profilePictureBytes = user.getProfilePicture();

    if (profilePictureBytes != null) {
        String encodedImage = Base64.getEncoder().encodeToString(profilePictureBytes);
        model.addAttribute("encodedImage", encodedImage);
    }
    return "user-page";
}

On a user-page html file i try to decode it like this:

<img th:attr="src=${'data:image/jpeg;base64,' + encodedImage}" alt="Profile Picture">

This solution works for smaller images but throws an exception when the encoded image exceeds 100 000 characters:

org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "'data:image/jpeg;base64,' + encodedImage" (template: "user-page" - line 27, col 6)

org.springframework.expression.spel.SpelEvaluationException: EL1078E: Concatenated string is too long, exceeding the threshold of '100 000' characters

Is there a way to circumvent this limit or should i change the whole logic of the program instead? Thank you.

答案1

得分: 1

这部分文本的翻译如下:

"This one is tricky! TY, @Andrey(, again;) for exactly pointing the "issue". I'm not sure, whether it is worth to open a spring issue/request/enhancement for this.

But:

  • (as it looks, github search) this check only applies on the (Spring EL) "string concatenation"
  • to "circumvent", we can ... use thymeleaf features:
    • Couldn't make it work with "inline expressions", yet... (seems not to work with "attrs")
    • but with th:attrappend !! Is there a way to display image encoded into a string longer than 100 000 characters? (Java, Spring, Thymeleaf) (instead of Spring EL string concat;)

Resulting template:

<img src="data:image/jpeg;base64," th:attrappend="src=${encodedImage}" alt="Profile Picture">

(Test) Controller used:

@Controller
class DemoController {

	final String encodedImage;

	public DemoController(
			@Value("classpath:/bigImage.jpg") /* source: https://github.com/samdutton/simpl/blob/main/bigimage/bigImage.jpg */
			Resource bigPic) throws IOException {
		this.encodedImage = Base64.getEncoder().encodeToString(bigPic.getContentAsByteArray());
	}

	@ModelAttribute("encodedImage")
	public String encodedImage() throws IOException {
		return encodedImage;
	}

	@GetMapping("/test")
	public String test() {
		return "test";
	}
}
```"

### Generally
"These type of things" belong "into the caches of load balancers"! (..and not into the "memory" (`byte[], Base64`...) of your "back ends" :)

### Advanced
It'd be nice to "attach" these (kind of) things (to html/http response) similar to https://www.thymeleaf.org/doc/articles/springmail.html, like:

- template:
  ```lang-html
  <img src="sample.png" th:src="|cid:${imageResourceName}|" />
  • but unfortunately we can't (I didn't find it yet, as in MimeMessage addInline)

Another (Simple) Workaround

@ModelAttribute("encodedImageAttr")
public String encodedImageAttr() throws IOException {
    return String.format("data:image/jpeg;base64,%s", encodedImage);;
}

...serve the complete attribute value instead of the "base64 part".

Template then looks like:

<img src="" th:attr="src=${encodedImageAttr}" alt="Profile Picture">

(I also tried with template SpEL th:attr="src=${#T(java.lang.String).format('data:image/jpeg;base64,%s', encodedImageAttr)}", but failed due to:

...
Caused by: org.attoparser.ParseException: Instantiation of new objects and access to static classes or parameters is forbidden in this context (template: "test" - line 6, col 17)
	at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
	at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
	at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
	... 52 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes or parameters is forbidden in this context (template: "test" - line 6, col 17)
	at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.obtainComputedSpelExpression(SPELVariableExpressionEvaluator.java:309)
	at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:182)
	at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
	at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
	at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
...
```"

如果需要进一步的翻译,请告诉我。

<details>
<summary>英文:</summary>

This one is tricky! TY, @Andrey(, again;) for exactly pointing the &quot;issue&quot;. I&#39;m not sure, whether it is worth to open a spring issue/request/enhancement for this.

But:
- (as it looks, github search) this check only applies on the (Spring EL) &quot;string concatenation&quot;
- to &quot;circumvent&quot;, we can ... use thymeleaf features:
  - Couldn&#39;t make it work with &quot;inline expressions&quot;, yet... (seems not to work with &quot;attrs&quot;)
  - but with `th:attrappend` !! ;) (instead of Spring EL string concat;)

Resulting template:
```lang-html
&lt;img src=&quot;data:image/jpeg;base64,&quot; th:attrappend=&quot;src=${encodedImage}&quot; alt=&quot;Profile Picture&quot;&gt;

(Test) Controller used:

@Controller
class DemoController {

	final String encodedImage;

	public DemoController(
			@Value(&quot;classpath:/bigImage.jpg&quot;) /* source: https://github.com/samdutton/simpl/blob/main/bigimage/bigImage.jpg */
			Resource bigPic) throws IOException {
		this.encodedImage = Base64.getEncoder().encodeToString(bigPic.getContentAsByteArray());
	}

	@ModelAttribute(&quot;encodedImage&quot;)
	public String encodedImage() throws IOException {
		return encodedImage;
	}

	@GetMapping(&quot;/test&quot;)
	public String test() {
		return &quot;test&quot;;
	}
}

Generally

"These type of things" belong "into the caches of load balancers"! (..and not into the "memory" (byte[], Base64...) of your "back ends" Is there a way to display image encoded into a string longer than 100 000 characters? (Java, Spring, Thymeleaf)

Advanced

It'd be nice to "attach" these (kind of) things (to html/http response) similar to https://www.thymeleaf.org/doc/articles/springmail.html, like:

  • template:
    &lt;img src=&quot;sample.png&quot; th:src=&quot;|cid:${imageResourceName}|&quot; /&gt;
    
  • but unfortunately we can't (I didn't find it yet, as in MimeMessage addInline)

Another (Simple) Workaround

@ModelAttribute(&quot;encodedImageAttr&quot;)
public String encodedImageAttr() throws IOException {
    return String.format(&quot;data:image/jpeg;base64,%s&quot;, encodedImage);;
}

...serve the complete attribute value instead of the "base64 part".

Template then looks like:

&lt;img src=&quot;&quot; th:attr=&quot;src=${encodedImageAttr}&quot; alt=&quot;Profile Picture&quot;&gt;

(I also tried with template SpEL th:attr=&quot;src=${#T(java.lang.String).format(&#39;data:image/jpeg;base64,%s&#39;, encodedImageAttr)}&quot;, but failed due to:

...
Caused by: org.attoparser.ParseException: Instantiation of new objects and access to static classes or parameters is forbidden in this context (template: &quot;test&quot; - line 6, col 17)
	at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
	at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
	at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
	... 52 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes or parameters is forbidden in this context (template: &quot;test&quot; - line 6, col 17)
	at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.obtainComputedSpelExpression(SPELVariableExpressionEvaluator.java:309)
	at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:182)
	at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
	at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
	at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
...

)

huangapple
  • 本文由 发表于 2023年5月7日 16:36:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76192905.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定