29

我正在开发一个 java web 应用程序,其中文件将存储在数据库中。最初,我们通过简单地调用getBytes我们的结果集来检索数据库中已经存在的文件:

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

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

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

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

我的直接想法是检索数据库中的数据流,getBinaryStream并以某种方式将其转换InputStreamDataHandler内存有效的方式。不幸的是,似乎没有直接的方法可以将 a 转换InputStreamDataHandler. 我一直在玩的另一个想法是从 中读取数据块并将InputStream它们写入OutputStream. DataHandler但是......我找不到一种方法来创建一个“空” ,当我打电话时DataHandler返回一个非空......OutputStreamgetOutputStream

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

4

8 回答 8

22

“Kathy Van Stone”的答案实现:

首先创建 helper 类,它从 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;
于 2012-05-28T11:02:34.797 回答
19

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

希望能帮助到你!

于 2010-11-29T17:23:01.857 回答
17

我的方法是编写一个自定义类来实现DataSource包装你的InputStream. 然后创建DataHandler给它 created DataSource

于 2010-05-13T21:56:49.490 回答
4

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

于 2011-01-30T23:32:53.590 回答
1

(bugs_) 代码对我不起作用。我使用 DataSource 创建电子邮件附件(来自具有inputStreamname的对象)和附件内容丢失。看起来 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");
    }

}
于 2016-02-11T17:03:00.470 回答
0

我遇到InputStream了两次请求时遇到的情况DataSource:使用 Logging Handler 和 MTOM 功能。使用此代理流解决方案,我的实现工作正常:

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 "";
    }
}
于 2017-04-29T00:22:40.437 回答
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));
于 2018-02-06T02:04:59.237 回答
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>

于 2021-04-15T13:59:28.263 回答