我正在研究一个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
...
有人这样做过吗?我很感激你能给我的任何帮助或者正确的方向。
答案 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>