如何将InputStream转换为DataHandler?

时间:2010-05-13 21:49:22

标签: java inputstream outputstream

我正在研究一个java Web应用程序,其中文件将存储在数据库中。最初我们只是在结果集上调用getBytes来检索数据库中已有的文件:

byte[] bytes = resultSet.getBytes(1);
...

然后使用明显的构造函数将此字节数组转换为DataHandler

dataHandler=new DataHandler(bytes,"application/octet-stream");

这很有效,直到我们开始尝试存储和检索更大的文件。将整个文件内容转储到字节数组中,然后构建DataHandler只需要太多内存。

我的直接想法是使用getBinaryStream检索数据库中的数据流,并以节省内存的方式将InputStream转换为DataHandler。不幸的是,将InputStream转换为DataHandler似乎没有直接的方法。我一直在玩的另一个想法是从InputStream读取数据块并将其写入OutputStream的{​​{1}}。但是......当我打电话给DataHandler时,我无法找到一种方法来创建一个返回非空DataHandler的“空”OutputStream ...

有人这样做过吗?我很感激你能给我的任何帮助或者正确的方向。

8 个答案:

答案 0 :(得分:17)

“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;

答案 1 :(得分:16)

我的方法是编写一个实现DataSource的自定义类来包装您的InputStream。然后创建DataHandler,为其创建DataSource

答案 2 :(得分:16)

我也遇到过这个问题。如果您的源数据是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;

希望它有所帮助!

答案 3 :(得分:3)

请注意,DataSource的getInputStream必须在每次调用时返回一个新的InputStream。这意味着,你需要复制到某个地方。 有关详细信息,请参阅 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4267294

答案 4 :(得分:1)

(bugs_)代码对我不起作用。我使用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");
    }

}

答案 5 :(得分:0)

我遇到InputStream DataSource两次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 ""; } } 请求的情况:使用Logging Handler和MTOM功能。 使用this proxy stream solution我的实现工作正常:

totalvotes = {}
for i in range(0,len(votes)):
     if not votes[i][0] in totalvotes:
          totalvotes[votes[i][0]] = 0
     totalvotes[votes[i][0]] = totalvotes[votes[i][0]]+int(votes[i][2])
print(totalvotes)

答案 6 :(得分:0)

这是一个专门使用Spring Boot org.springframework.core.io.Resource对象的答案,我想我们很多人都在这里。请注意,您可能需要修改下面代码中的内容类型,因为我正在将png文件插入到html格式的电子邮件中。

注意:正如其他人所提到的,仅仅附加一个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));

答案 7 :(得分:0)

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import org.apache.commons.io.IOUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

.

 DataSource ds = new ByteArrayDataSource(convertHtmlToPdf("<span>html here</span>"), "application/pdf");

 DataHandler dataHandler = new DataHandler(ds);

.

public static byte[] convertHtmlToPdf(String htmlString) throws IOException, DocumentException {
    Document document = new Document();

    ByteArrayOutputStream out = new ByteArrayOutputStream();

    PdfWriter writer = PdfWriter.getInstance(document, out);
    document.open();

    InputStream in = IOUtils.toInputStream(htmlString);
    XMLWorkerHelper.getInstance().parseXHtml(writer, document, in);
    document.close();

    return out.toByteArray();
}

可能的错误:必须关闭元标记。 <meta></meta>