質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

Q&A

解決済

2回答

13330閲覧

AWSのS3にアップロードができない【Java】

sequence

総合スコア29

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

0グッド

0クリップ

投稿2017/01/20 08:13

やりたいこと

画像がBufferedImageの形式で存在する時に
その画像をAWSのS3にアップロードしたいです。

環境

  • Java8
  • PlayFramework

現状

現在は下記のコードでアップロードをしようとするとエラーは出ないのですが、
アップロードがされません。

BufferedImage thumbnailImage = ... // S3に対してMeta情報を付加 ObjectMetadata metaData = new ObjectMetadata(); // 拡張子を取得 String extension = SetExtension.setExtension(imageFile.getFilename()); // byte配列からS3へアップロードするInputStreamへ変換をする ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(thumbnailImage, extension, baos); baos.flush(); byte[] imageInByte = baos.toByteArray(); baos.close(); in = new ByteArrayInputStream(imageInByte); // content-typeを設定 metaData.setContentType("image/" + extension); // S3に保存 s3.putObject(new PutObjectRequest(BUCKET_NAME, fileName, in, metaData));

これを実行した時は下記のメッセージがコンソール上に表示されてアップロードできません。

[warn] c.a.s.s.AmazonS3Client - No content length specified for stream data. Stream contents will be buffered in memory and could result in out of memory errors.

対応

InputStreamのバイト長を予測させないといけないということで、下記のURLを参考に変更をしました。
https://groups.google.com/forum/#!topic/google-appengine-stackoverflow/yo40fKxqrv8

BufferedImage thumbnailImage = ... // S3に対してMeta情報を付加 ObjectMetadata metaData = new ObjectMetadata(); // 拡張子を取得 String extension = SetExtension.setExtension(imageFile.getFilename()); // byte配列からS3へアップロードするInputStreamへ変換をする ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(thumbnailImage, extension, baos); baos.flush(); byte[] imageInByte = baos.toByteArray(); baos.close(); in = new ByteArrayInputStream(imageInByte); // バイト長を取得(追加) byte[] contentBytes = IOUtils.toByteArray(in); Long contentLength = Long.valueOf(contentBytes.length); // content-typeを設定 metaData.setContentType("image/" + extension); // バイト長を設定(追加) metaData.setContentLength(contentLength); // S3に保存 s3.putObject(new PutObjectRequest(BUCKET_NAME, fileName, in, metaData));

これでアップロード処理を行うと下記のエラーがでてしまいます。

[error] p.c.s.n.PlayDefaultUpstreamHandler - Cannot invoke the action com.amazonaws.AmazonClientException: Data read has a different length than the expected: dataLength=0; expectedLength=19539; includeSkipped=false; in.getClass()=class com.amazonaws.internal.ReleasableInputStream; markedSupported=true; marked=0; resetSinceLastMarked=false; markCount=1; resetCount=0 at com.amazonaws.util.LengthCheckInputStream.checkLength(LengthCheckInputStream.java:150) ~[aws-java-sdk-core-1.10.62.jar:na] at com.amazonaws.util.LengthCheckInputStream.read(LengthCheckInputStream.java:110) ~[aws-java-sdk-core-1.10.62.jar:na] at com.amazonaws.internal.SdkFilterInputStream.read(SdkFilterInputStream.java:72) ~[aws-java-sdk-core-1.10.62.jar:na] at com.amazonaws.services.s3.internal.MD5DigestCalculatingInputStream.read(MD5DigestCalculatingInputStream.java:98) ~[aws-java-sdk-s3-1.10.62.jar:na] at com.amazonaws.internal.SdkFilterInputStream.read(SdkFilterInputStream.java:72) ~[aws-java-sdk-core-1.10.62.jar:na] at com.amazonaws.event.ProgressInputStream.read(ProgressInputStream.java:151) ~[aws-java-sdk-core-1.10.62.jar:na] at com.amazonaws.internal.SdkFilterInputStream.read(SdkFilterInputStream.java:72) ~[aws-java-sdk-core-1.10.62.jar:na] at org.apache.http.entity.InputStreamEntity.writeTo(InputStreamEntity.java:138) ~[httpcore-4.3.3.jar:4.3.3] at com.amazonaws.http.RepeatableInputStreamRequestEntity.writeTo(RepeatableInputStreamRequestEntity.java:153) ~[aws-java-sdk-core-1.10.62.jar:na] at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:89) ~[httpcore-4.3.3.jar:4.3.3] [error] application -

どなたかご教授お願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

// バイト長を取得(追加)

byte[] contentBytes = IOUtils.toByteArray(in); Long contentLength = Long.valueOf(contentBytes.length);

この toByteArray で in の読み込みが進んでしまい、最後まで読み切った状態になっていると思います。

// S3に保存

s3.putObject(new PutObjectRequest(BUCKET_NAME, fileName, in, metaData));

これで中身を読み出そうとしても、最後まで読み切ってしまっているので、中身の長さが0バイトになり、

Data read has a different length than the expected: dataLength=0; expectedLength=19539;

「読み込まれたデータの長さは 0バイトで期待されていた長さ19539バイトと異なっている」というエラーになっています。

バイト長を取得するのに toByteArray とかを使わなくても imageInByte の長さを取ればいいのでは?

投稿2017/01/20 09:21

mit0223

総合スコア3401

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sequence

2017/01/20 09:47

ご回答ありがとうございます。 こちらの方法でうまくいきました。 InputStreamについて全然理解していなかったので、しっかり理解していこうと思います。
guest

0

以下変更でいけませんか?

diff

1+ S3Object s3Object = new S3Object(); 2+ s3Object.setObjectContent(in); 3 s3.putObject(new PutObjectRequest(BUCKET_NAME, fileName, in, metaData)); 4+ s3Object.close();

投稿2017/01/20 08:30

moonphase

総合スコア6621

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sequence

2017/01/20 09:45 編集

ご回答ありがとうございます。 こちらの場合ですと、 上記に記載したエラーが出力されてしまいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問