私はファイルをデータベースに保存するJava Webアプリケーションに取り組んでいます。もともとは、結果セットでgetBytes
を呼び出すだけで、DBに既にファイルを取得していました。
byte[] bytes = resultSet.getBytes(1);
...
次に、このバイト配列は、明白なコンストラクターを使用してDataHandler
に変換されました。
dataHandler=new DataHandler(bytes,"application/octet-stream");
これは、大きなファイルを保存および取得しようとするまではうまくいきました。ファイルの内容全体をバイト配列にダンプし、その中からDataHandler
を作成するには、必要なメモリが多すぎます。
私の当面のアイデアは、getBinaryStream
を使用してデータベース内のデータのストリームを取得し、そのInputStream
をメモリ効率の良い方法でDataHandler
に変換することです。残念ながら、InputStream
をDataHandler
に直接変換する方法はないようです。私が遊んでいたもう1つのアイデアは、InputStream
からデータのチャンクを読み取り、OutputStream
のDataHandler
に書き込むことです。しかし... DataHandler
を呼び出したときにnull以外のOutputStream
を返す「空の」getOutputStream
を作成する方法が見つかりません。
誰もこれをしましたか?あなたが私に与えることができるか、正しい方向に導くことができるどんな助けでも感謝します。
私のアプローチは、DataSource
をラップするInputStream
を実装するカスタムクラスを記述することです。次に、DataHandler
を作成し、作成されたDataSource
を指定します。
「Kathy Van Stone」からの回答の実装:
最初に、InputStreamからDataSourceを作成するヘルパークラスを作成します。
public class InputStreamDataSource implements DataSource {
private InputStream inputStream;
public InputStreamDataSource(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public InputStream getInputStream() throws IOException {
return inputStream;
}
@Override
public OutputStream getOutputStream() throws IOException {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public String getContentType() {
return "*/*";
}
@Override
public String getName() {
return "InputStreamDataSource";
}
}
そして、InputStreamからDataHandlerを作成できます。
DataHandler dataHandler = new DataHandler(new InputStreamDataSource(inputStream))
インポート:
import javax.activation.DataSource;
import Java.io.OutputStream;
import Java.io.InputStream;
私もこの問題に遭遇しました。ソースデータがbyte[]
AxisにはすでにInputStreamをラップしてDataHandlerオブジェクトを作成するクラスがあります。ここにコードがあります
//this constructor takes byte[] as input
ByteArrayDataSource rawData= new ByteArrayDataSource(resultSet.getBytes(1));
DataHandler data= new DataHandler(rawData);
yourObject.setData(data);
関連するインポート
import javax.activation.DataHandler;
import org.Apache.axiom.attachments.ByteArrayDataSource;
それが役に立てば幸い!
DataSourceのgetInputStreamは、呼び出されるたびに新しいInputStreamを返す必要があることに注意してください。つまり、1番目のどこかにコピーする必要があります。詳細については、 http://bugs.Sun.com/bugdatabase/view_bug.do?bug_id=4267294 を参照してください
(bugs_)codeが機能しません。 DataSourceを使用して、電子メールへの添付ファイル(inputStreamおよびnameを持つオブジェクトから)および添付ファイルのコンテンツを失います。 Stefanは正しいようで、毎回新しいinputStreamを返す必要があります。少なくとも私の特定のケースでは。次の実装では問題に対処します。
public class InputStreamDataSource implements DataSource {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private final String name;
public InputStreamDataSource(InputStream inputStream, String name) {
this.name = name;
try {
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String getContentType() {
return new MimetypesFileTypeMap().getContentType(name);
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(buffer.toByteArray());
}
@Override
public String getName() {
return name;
}
@Override
public OutputStream getOutputStream() throws IOException {
throw new IOException("Read-only data");
}
}
ここでは、Spring Boot org.springframework.core.io.Resourceオブジェクトを具体的に操作するための答えを示します。 html形式の電子メールにpngファイルを挿入しているため、以下のコードでコンテンツタイプを変更する必要がある場合があることに注意してください。
注:他の人が述べたように、InputStreamをアタッチするだけでは複数回使用されるので十分ではなく、Resource.getInputStream()にマッピングするだけでうまくいきます。
public class SpringResourceDataSource implements DataSource {
private Resource resource;
public SpringResourceDataSource(Resource resource) {
this.resource = resource;
}
@Override
public InputStream getInputStream() throws IOException {
return resource.getInputStream();
}
@Override
public OutputStream getOutputStream() throws IOException {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public String getContentType() {
return "image/png";
}
@Override
public String getName() {
return "SpringResourceDataSource";
}
}
クラスの使用法は次のようになります。
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource logoImage = pathMatchingResourcePatternResolver.getResource("/static/images/logo.png");
MimeBodyPart logoBodyPart = new MimeBodyPart();
DataSource logoFileDataSource = new SpringResourceDataSource(logoImage);
logoBodyPart.setDataHandler(new DataHandler(logoFileDataSource));
InputStream
がDataSource
から2回要求されたとき、私は状況に遭遇しました:MTOM機能と一緒にLogging Handlerを使用します。 このプロキシストリームソリューション を使用すると、実装は正常に動作します。
import org.Apache.commons.io.input.CloseShieldInputStream;
import javax.activation.DataHandler;
import javax.activation.DataSource;
...
private static class InputStreamDataSource implements DataSource {
private InputStream inputStream;
@Override
public InputStream getInputStream() throws IOException {
return new CloseShieldInputStream(inputStream);
}
@Override
public OutputStream getOutputStream() throws IOException {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public String getContentType() {
return "application/octet-stream";
}
@Override
public String getName() {
return "";
}
}