8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何在将图像上传到 S3 之前从图像中剥离 EXIF 元数据,而无需将整个文件加载到内存中

gregory 2月前

45 0

我有一项使用 MultipartFile 将图像上传到 AWS S3 的服务。这些图像随后将作为公共文件提供。存在一个安全问题:这些图像可能包含敏感的 EXIF 元数据...

我有一项使用 MultipartFile 将图像上传到 AWS S3 的服务。这些图像随后将作为公共文件提供。存在一个安全问题:这些图像可能包含敏感的 EXIF 元数据(例如地理位置数据),必须在公开之前将其删除。

问题:我需要从这些图像中剥离 EXIF 元数据,而无需将整个文件加载到内存中,因为某些图像可能非常大。

我目前的做法是:

private S3Service.S3UploadedFile uploadImage(MultipartFile file) {
    try {
        ByteArrayOutputStream originalOut = stripMetadata(file.getInputStream());

        final PipedInputStream in = new PipedInputStream();
        new Thread(() -> {
            try (final PipedOutputStream newOut = new PipedOutputStream(in)) {
                originalOut.writeTo(newOut);
            } catch (IOException e) {
                // logging and exception handling should go here
            }
        }).start();

        S3File processedS3File = S3File.builderOf(in, file.getContentType())
                .isPublic(true)
                .contentLength((long) originalOut.size())
                .build();

        return s3Service.upload(bucketName, processedS3File);

    } catch (IOException | ImageWriteException | ImageReadException e) {
        throw new RuntimeException("ERR");
    }
}

public static ByteArrayOutputStream stripMetadata(InputStream imageInputStream)
        throws IOException, ImageWriteException, ImageReadException {

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    ExifRewriter exifRewriter = new ExifRewriter();
    exifRewriter.removeExifMetadata(imageInputStream, outputStream);

    return outputStream;
}

管道流的使用基于以下答案: https://.com/a/23874232/6157949

但是,在该 stripMetadata 方法中,我使用 Apache Commons Imaging 库来删除 EXIF 元数据。问题是它需要一个 OutputStream,而我目前使用的是 ByteArrayOutputStream,它会将整个图像加载到内存中。

我需要帮助:

我需要有关如何调整此方法的指导,以便我可以从图像中剥离 EXIF 元数据并将其上传到 S3,而无需将整个文件加载到内存中。

  • 有没有办法将图像通过元数据剥离过程直接传输到 S3?
  • 我可以使用不同的方法或库来更有效地处理大文件吗?

任何帮助或建议都将不胜感激!

帖子版权声明 1、本帖标题:如何在将图像上传到 S3 之前从图像中剥离 EXIF 元数据,而无需将整个文件加载到内存中
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由gregory在本站《java》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 如果您只关心 JPEG 交换格式,此格式包含您可以在写入时流式传输的片段,也可以选择跳过这些片段。使用 APP1 标记和 \'Exif\' 作为标识符字符串,可以轻松识别 Exif 片段。

  • @HaraldK,jpeg 方法就是一个例子,所有这些类型都受支持:\'jpeg\'、\'jpg\'、\'png\'、\'gif\'、\'bmp\'、\'tiff\'。

  • 您应该简单地将其传递 PipedOutputStream 给调用 exifRewriter.removeExifMetadata ,而不是在堆上创建缓冲区。

    我重写了你的代码(未经测试)以清楚地表明我的意思:

    private S3Service.S3UploadedFile uploadImage(MultipartFile file) {
      try {
        ExifRewriter exifRewriter = new ExifRewriter();
        final PipedInputStream in = new PipedInputStream();
    
        new Thread(() -> {
          try (final PipedOutputStream newOut = new PipedOutputStream(in)) {
            exifRewriter.removeExifMetadata(file.getInputStream(), newOut);
          } catch (IOException e) {
            // logging and exception handling should go here
          }
        }).start();
    
        S3File processedS3File = S3File.builderOf(in, file.getContentType())
            .isPublic(true)
            .contentLength((long) originalOut.size())
            .build();
    
        return s3Service.upload(bucketName, processedS3File);
      } catch (IOException | ImageWriteException | ImageReadException e) {
          throw new RuntimeException("ERR");
      }
    }
    
返回
作者最近主题: