Java 返回图像AWS S3(S3Object)弹簧座控制器

Java 返回图像AWS S3(S3Object)弹簧座控制器,java,spring,amazon-web-services,amazon-s3,Java,Spring,Amazon Web Services,Amazon S3,我正在尝试从S3存储桶返回图像。一切都很完美,我的服务上传并获取图像,但问题是当我试图通过REST控制器返回图像时,图像不会出现在浏览器上 这里是我从S3获取图像的地方: public S3Object getImageFromS3Bucket(String fileName) { S3Object object = s3client.getObject(new GetObjectRequest(bucketName, fileName)); return object; }

我正在尝试从S3存储桶返回图像。一切都很完美,我的服务上传并获取图像,但问题是当我试图通过REST控制器返回图像时,图像不会出现在浏览器上

这里是我从S3获取图像的地方:

public S3Object getImageFromS3Bucket(String fileName) {
    S3Object object = s3client.getObject(new GetObjectRequest(bucketName, fileName));
    return object;
}

public byte[] getByteArrayFromImageS3Bucket(String fileName) throws IOException {
    InputStream in = getImageFromS3Bucket(fileName).getObjectContent();
    byte[] byteArray = IOUtils.toByteArray(in);
    in.close();

    return byteArray;
}
这是我的控制器:

@RequestMapping(value = "/getImage/{fileName}", method = RequestMethod.GET)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public ResponseEntity<byte[]> downloadImage(@PathVariable("fileName") String fileName) throws IOException {
    byte[] media = s3BucketTestService.getByteArrayFromFile(fileName);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.IMAGE_PNG);
    headers.setContentLength(media.length);

    return new ResponseEntity<>(media, headers, HttpStatus.OK);
}
我的配置中也有这个bean:

@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
    ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
    arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
    return arrayHttpMessageConverter;
}

private List<MediaType> getSupportedMediaTypes() {
    List<MediaType> list = new ArrayList<MediaType>();
    list.add(MediaType.IMAGE_JPEG);
    list.add(MediaType.IMAGE_PNG);
    list.add(MediaType.APPLICATION_OCTET_STREAM);
    return list;
}
@Bean
public ByteArrayHttpMessageConverter ByteArrayHttpMessageConverter(){
ByteArrayHttpMessageConverter arrayHttpMessageConverter=新建ByteArrayHttpMessageConverter();
arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
返回阵列HttpMessageConverter;
}
私有列表getSupportedMediaTypes(){
列表=新的ArrayList();
添加(MediaType.IMAGE\u JPEG);
添加(MediaType.IMAGE\u PNG);
添加(MediaType.APPLICATION\u OCTET\u STREAM);
退货清单;
}
谁知道我做错了什么?浏览器会创建一个png图像,其大小与我想要获取的文件的大小完全相同,所以我想唯一的问题是图像的可视化


PD:我不想让图像可下载,我只想生成该资源,以便前端可以读取它。

可能是一个愚蠢的问题,但您非常确定图像的MIME类型实际上是PNG吗?也许浏览器一直在做一些MIME嗅探,并且在发现广告内容类型和文件格式之间感到困惑?我看到您已经设置了
X-Content-Type-Options:nosniff
,但我只是想首先确保文件格式正确。

尝试使用ImageIO API将原始字节从S3存储桶转换为图像字节,如下所示:

public byte[] getByteArrayFromImageS3Bucket(String fileName) throws IOException {
    InputStream in = getImageFromS3Bucket(fileName).getObjectContent();

    BufferedImage imageFromAWS = ImageIO.read(in);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(imageFromAWS, "png", baos );
    byte[] imageBytes = baos.toByteArray();
    in.close();
    return imageBytes;

}

我回答了一个类似的问题,它与PDF有关。如果您只是将MediaType更改为PNG/JPEG,它应该可以工作。看一看。

我可能还建议,对照原始文件检查文件的哈希和,您可以通过多种方式执行此操作-可能最常见的是sha或md5求和。是的,我仔细检查了!我100%确定这是一个PNG文件。我会这样做以防万一…如果我返回图像作为base64,我可以转换它并显示它,所以我的图像在那里,它是PNG,问题仍然是一样的。也许我最终只会返回base64,让前端负责处理它……我仍然建议通过哈希和(如sha/md5)来确认二进制相等性。同样如上所述,您是通过AJAX还是作为图像标记的src属性来获取图像?您是否尝试过直接在浏览器中粘贴URL或将wget的输出保存到URL?我尝试过使用它,但它返回以下信息:
InputStream资源[通过InputStream加载的资源]无法解析为URL
明白了,您是否尝试在浏览器本身上渲染图像?这就是原因,在我的示例中,它将打开另存为弹出窗口。我认为您可能正在捕获流,可能是在Ajax调用中。你能在调用服务的地方发布客户端代码吗?我只能访问后端!所以,是的,我只有浏览器和邮递员):我在邮递员中测试过,它确实有效。尝试进行系统调试-只需去掉{filename}路径参数并尝试点击服务。如果它有效,那么让它动态化,做进一步的移动…像那样。对不起,它对我不起作用):我不知道怎么了,也许我们使用的是不同版本的库。。。我将返回base64字符串这是唯一有效的解决方案。我用另一种方法,使用
IOUtils.toByteArray(in)并使其不那么复杂。假定文件名代表@dgarceran
public byte[] getByteArrayFromImageS3Bucket(String fileName) throws IOException {
    InputStream in = getImageFromS3Bucket(fileName).getObjectContent();

    BufferedImage imageFromAWS = ImageIO.read(in);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(imageFromAWS, "png", baos );
    byte[] imageBytes = baos.toByteArray();
    in.close();
    return imageBytes;

}