【问题标题】:Uploading Base64 encoded image to Amazon s3 using java使用 java 将 Base64 编码图像上传到 Amazon s3
【发布时间】:2015-09-05 12:58:38
【问题描述】:

我正在尝试使用 Amazon 的 Java API 将文件上传到 Amazon S3 存储。代码是

Byte[] b = data.getBytes();
InputStream stream  = new ByteArrayInputStream(b);
//InputStream stream = new FileInputStream(new File("D:/samples/test.txt"));
AWSCredentials credentials = new BasicAWSCredentials("<key>", "<key1>");
AmazonS3 s3client = new AmazonS3Client(credentials);
s3client.putObject(new PutObjectRequest("myBucket",name,stream, new ObjectMetadata()));

当我在注释前两行并取消注释第三行之后运行代码时,即streamFileoutputStream,文件被正确上传。但是当data是base64编码的String,也就是图片数据时,文件上传了,但是图片损坏了。 亚马逊文档说我需要创建并附加一个 POST 策略和签名才能使其正常工作。我怎么能在java中做到这一点?我没有使用html 表单进行上传。

【问题讨论】:

  • 非常好的问题+1
  • 问得好,有没有运气好?

标签: java amazon-web-services amazon-s3


【解决方案1】:

首先你应该从字符串的开头删除 data:image/png;base64:

示例代码块

byte[] bI = org.apache.commons.codec.binary.Base64.decodeBase64((base64Data.substring(base64Data.indexOf(",")+1)).getBytes());

InputStream fis = new ByteArrayInputStream(bI);

AmazonS3 s3 = new AmazonS3Client();
Region usWest02 = Region.getRegion(Regions.US_WEST_2);
s3.setRegion(usWest02);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(bI.length);
metadata.setContentType("image/png");
metadata.setCacheControl("public, max-age=31536000");
s3.putObject(BUCKET_NAME, filename, fis, metadata);
s3.setObjectAcl(BUCKET_NAME, filename, CannedAccessControlList.PublicRead);

【讨论】:

  • 使用 java8,您可以使用内置工具解码字符串:byte[] bI = java.util.Base64.getDecoder.decode(base64Data)
【解决方案2】:

这是一个 DTO 类,它接收直接从您的客户端传入的 base64Image 数据,并解析成可以在您的 uploadToAwsS3 方法中轻松传递的不同组件:

public class Base64ImageDto {

    private byte[] imageBytes;
    private String fileName;
    private String fileType;
    private boolean hasErrors;
    private List<String> errorMessages;
    private static final List<String> VALID_FILE_TYPES = new ArrayList<String>(3);

    static {
        VALID_FILE_TYPES.add("jpg");
        VALID_FILE_TYPES.add("jpeg");
        VALID_FILE_TYPES.add("png");
    }

    public Base64ImageDto(String b64ImageData, String fileName) {
        this.fileName = fileName;
        this.errorMessages = new ArrayList<String>(2);
        String[] base64Components = b64ImageData.split(",");

        if (base64Components.length != 2) {
            this.hasErrors = true;
            this.errorMessages.add("Invalid base64 data: " + b64ImageData);
        }

        if (!this.hasErrors) {
            String base64Data = base64Components[0];
            this.fileType = base64Data.substring(base64Data.indexOf('/') + 1, base64Data.indexOf(';'));

            if (!VALID_FILE_TYPES.contains(fileType)) {
                this.hasErrors = true;
                this.errorMessages.add("Invalid file type: " + fileType);
            }

            if (!this.hasErrors) {
                String base64Image = base64Components[1];
                this.imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(base64Image);
            }
        }
    }

    public byte[] getImageBytes() {
        return imageBytes;
    }

    public void setImageBytes(byte[] imageBytes) {
        this.imageBytes = imageBytes;
    }

    public boolean isHasErrors() {
        return hasErrors;
    }

    public void setHasErrors(boolean hasErrors) {
        this.hasErrors = hasErrors;
    }

    public List<String> getErrorMessages() {
        return errorMessages;
    }

    public void setErrorMessages(List<String> errorMessages) {
        this.errorMessages = errorMessages;
    }

    public String getFileType() {
        return fileType;
    }

    public void setFileType(String fileType) {
        this.fileType = fileType;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
}

这是您可以添加到 AwsS3Service 的方法,该方法将把对象放在那里(注意:您可能没有使用传输管理器来管理您的 put,因此您需要相应地更改该代码强>):

public void uploadBase64Image(Base64ImageDto base64ImageDto, String pathToFile) {
    InputStream stream = new ByteArrayInputStream(base64ImageDto.getImageBytes());

    ObjectMetadata metadata = new ObjectMetadata();
    metadata.setContentLength(base64ImageDto.getImageBytes().length);
    metadata.setContentType("image/"+base64ImageDto.getFileType());

    String bucketName = awsS3Configuration.getBucketName();
    String key = pathToFile + base64ImageDto.getFileName();

    try {
        LOGGER.info("Uploading file " + base64ImageDto.getFileName() + " to AWS S3");
        PutObjectRequest objectRequest = new PutObjectRequest(bucketName, key, stream, metadata);
        objectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
        Upload s3FileUpload = s3TransferManager.upload(objectRequest);
        s3FileUpload.waitForCompletion();
    } catch (Exception e) {
        e.printStackTrace();
        LOGGER.info("Error uploading file " + base64ImageDto.getFileName() + " to AWS S3");
    }      
}

【讨论】:

    【解决方案3】:

    对于使用更高版本 SDK 的用户: 实现组:software.amazon.awssdk,名称:s3,版本:2.10.3

        byte[] bI = Base64.decodeBase64((base64Data.substring(base64Data.indexOf(",") + 1)).getBytes());
    
        InputStream fis = new ByteArrayInputStream(bI);
    
        amazonS3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(fileName)
                        .contentType(contentType)
                        .contentLength(Long.valueOf(bI.length))
                        .build(),
                RequestBody.fromInputStream(fis, Long.valueOf(bI.length)));
    

    【讨论】:

      【解决方案4】:

      如何上传图片(png / jpg)的示例代码如下。 --

      try {
          BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKey, secretKey);
          AmazonS3 s3Client = 
          AmazonS3ClientBuilder.standard().withRegion(clientRegion)
                          .withCredentials(new 
          AWSStaticCredentialsProvider(awsCreds))
                          .build();
          PutObjectRequest request = new PutObjectRequest(bucketName, fileName, new File(fileToUpload));
          ObjectMetadata metadata = new ObjectMetadata();
          metadata.setContentType("image/jpg");
          request.setMetadata(metadata);
          s3Client.putObject(request.withCannedAcl(CannedAccessControlList.PublicRead));
      
          logger.info("File " + fileToUpload + " uploaded to AWS bucket " + bucketName);
      } catch (AmazonServiceException e) {
          logger.error(e);
          fileName = Common.NO_VALUE.toString();
      } catch (SdkClientException e) {
          logger.error(e);
          fileName = Common.NO_VALUE.toString();
      }
      

      但是,我没有使用任何编码或解码的概念。这个平面简单的元数据内容类型“image/jpg”有效。

      【讨论】:

        猜你喜欢
        • 2011-11-22
        • 2014-06-26
        • 2016-12-26
        • 1970-01-01
        • 2018-07-16
        • 2020-10-02
        • 2017-04-28
        • 2016-04-13
        • 2012-10-04
        相关资源
        最近更新 更多