我正在开发一个spring 3.2.7应用程序,它通过弹出控制器将存储在数据库中的签名作为base64字符串发送回用户浏览器,弹出控制器输出字节数组ResponseEntity。
图像总是被破坏,我没有在系统的这一部分工作,因为我在svn中双重检查并且由于我正在处理的分支已经创建,因此未触及控制器。
我能够将base64字符串转换为桌面上的图像,并且我还可以在弹出步骤之前将返回浏览器的字节数组转换为图像。
下面是我的代码,这显然在之前工作,或许有一些配置更改可能会导致这个?
@RequestMapping(value = "/submissions/signature/{type}/{id}", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<byte[]> getSignature(@PathVariable String type, @PathVariable Integer id) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String base64 = ... gets from db
byte[] bytes = Base64.decodeBase64(base64);
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIO.write(bi, "png", baos);
HttpHeaders headers = new HttpHeaders();
headers.setLastModified(Calendar.getInstance().getTime().getTime());
headers.setCacheControl("no-cache");
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(baos.toByteArray().length);
//Image as base64 string is ok in converter
System.out.println("BASE 64 IMAGE IS: " + base64);
//This image is created ok on desktop
FileOutputStream fos = new FileOutputStream("C:\\Users\\p\\Desktop\\test_signature.png");
fos.write(bytes);
fos.close();
//This image is created ok on desktop
FileOutputStream fos3 = new FileOutputStream("C:\\Users\\p\\Desktop\\test_signature_baos.png");
fos3.write(bytes);
fos3.close();
return new ResponseEntity<byte[]>(baos.toByteArray(), headers, HttpStatus.OK);
}
图像在浏览器中呈现如下:
<img id="userSignature" width="296" height="110" style="border:0px" src="/webapp/service/submissions/signature/user/${subid}" alt="User signature" />
我没有改变这个类,我被告知它确实有效,我能够从两个字节数组创建图像,它们没问题,看起来一样,我能够将签名字符串渲染为可测试,如: / p>
<IMG SRC="data:image/png;base64, <base_64_string>" ALT="">
是否有人遇到类似问题或知道可能导致此问题的原因?
我现在尝试从已经创建为png的文件系统发送图像,但也失败了。
我现在已经注意到CSV文件无法在应用程序中正确下载,并且它们以相同的方式流式传输:
@RequestMapping(value = "/results/csv", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<byte[]> getResultsInCsvFormat() throws IOException {
答案 0 :(得分:2)
我已经在InputStream
:
@RequestMapping(value = "/submissions/signature/{type}/{id}",
method = RequestMethod.GET)
public HttpEntity getFile(HttpServletResponse response,
@PathVariable String type,
@PathVariable Integer id) {
String base64 = "foo"; // get base-64 encoded string from db
byte[] bytes = Base64.decodeBase64(base64);
try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
StreamUtils.copy(inputStream, response.getOutputStream());
response.setContentType(MediaType.IMAGE_PNG_VALUE);
} catch (IOException e) {
// handle
}
return new ResponseEntity(HttpStatus.OK);
}
请注意,我没有使用ResponseBody
,而在我的工作版本中,我使用的是MediaType.APPLICATION_OCTET_STREAM_VALUE
,而不是实际的文件内容类型。
答案 1 :(得分:0)
好的,所以我现在解决了这个问题,感谢beerbajay,他告诉我直接通过流媒体直接下载回复是正常的,而且我应该看看ByteArrayHttpMessageConverter。
事实证明我在spring配置中犯了一个错误,我在阅读spring文档后意识到这一点,该文档告诉我使用&lt; mvc:annotation-driven /&gt;时自动注册了ByteArrayHttpMessageConverter。
mvc注释驱动标记已从配置中删除,因为我认为这是做同样的事情(我认为它只需要在spring上下文中声明一次):
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
看起来单独这个并不足以在应用程序中设置注释驱动,并且我已将标记添加回context.xml文件。
我不明白为什么这需要在两个地方,因为所有的xml配置都是通过相同的xml文件加载的,我认为是相同的弹簧上下文:
<import resource="config/properties.xml" />
<import resource="config/security.xml" />
<import resource="config/context.xml" />
<import resource="config/content-negotiation.xml" />
<import resource="config/rest-client.xml" />
答案 2 :(得分:0)
在Spring Boot 2.x中,对于Base64映像,可接受的解决方案对我不起作用。这是我返回Base64图像的方式:
@GetMapping(value = "/pixels/{id}", produces = MediaType.IMAGE_PNG_VALUE)
@ResponseBody
public byte[] pixelTracking(@PathVariable String id) {
// TODO: do whatever you want here
// return png image
String base64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=";
return Base64.getDecoder().decode(base64);
}
答案 3 :(得分:0)
我的解决方案是:
后端是spring boot,前端是reactjs
bug 是后端和前端的不同语法:java 使用 ("_","-") 和 web(reactjs,...) 使用 ("/","+") |
例如:“PGjQOA66-_ne-”转换为“PGjQOA66+//ne/+”
您可以在此链接中测试 base64 :https://onlinepngtools.com/convert-base64-to-png
后端代码:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
File file = new File(path);/// path : is external directory and local directory in server
FileInputStream imageInFile = new FileInputStream(path);
byte imageData[] = new byte[(int) file.length()];
imageInFile.read(imageData);
String base64 = encodeImage(imageData);
/// 1. Not show if size up 300KB !!! :|
/// 2. base64.replaceAll("_","/").replaceAll("-","+")
byte[] bytes = Base64.decodeBase64(base64.replaceAll("_","/").replaceAll("-","+"));
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(bytes));
ImageIO.write(bi, "png", baos);
HttpHeaders headers = new HttpHeaders();
headers.setLastModified(Calendar.getInstance().getTime().getTime());
headers.setCacheControl("no-cache");
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(baos.toByteArray().length);
return new ResponseEntity<byte[]>(baos.toByteArray(), headers, HttpStatus.OK);
和其他后端解决方案:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
File file = new File(path);/// path : is external directory file and local directory file in server, or path get of database.
FileInputStream imageInFile = new FileInputStream(path);
byte imageData[] = new byte[(int) file.length()];
imageInFile.read(imageData);
/// 1. Not show if size up 300KB !!! :| i dont now!
/// 2. base64.replaceAll("_","/").replaceAll("-","+")
String base64 = encodeImage(imageData).replaceAll("_","/").replaceAll("-","+");
return base64;
和 reactjs 代码是:
const [imageData, setImageData] = React.useState({});
setImageData(...request to backend);
<img src={`data:image/png;base64,${imageData}`} alt="This Is alert" />