我正在将MIME附件添加到这样的文档中
try{
var d = database.getView("Main").getFirstDocument()
var it = d.getFirstItem("Body")
var att:NotesEmbeddedObject = it.getEmbeddedObject("mydoc.docx")
var streamDOC:NotesStream = session.createStream()
streamDOC.setContents(att.getInputStream())
var newd;
newd = database.getView("NewD").getFirstDocument()
if(newd==null){
newd = database.createDocument()
newd.replaceItemValue("Form","Main")
var me = newd.createMIMEEntity("Body")
}else{
var me = newd.getMIMEEntity("Body")
}
var filename = "test.pdf"
var mc = me.createChildEntity();
var he = mc.createHeader("Content-Disposition")
he.setHeaderVal("attachment; filename=\"" + filename + "\"");
he = mc.createHeader("Content-ID");
he.setHeaderVal( "<" + filename + ">" );
mc.setContentFromBytes(streamDOC, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", NotesMIMEEntity.ENC_IDENTITY_8BIT);
newd.save()
print("success")
}catch(e){
print("fail " + e)
}
然后我再次提供一个删除按钮
var eo = nd.getDocument().getAttachment(att)
eo.remove()
nd.save()
附件已从文档中删除,在Ytria中,我看到$ FILE项已删除,但BODY项却未删除。问题是,如果我将新附件添加到同一文档,则以前删除的所有附件都会返回
这是删除附件之前文档的外观。
不幸的是,这里的文件大小为0Kb,因为我使用了错误的屏幕截图。从头开始,所有$ File项的大小均正确
这是我删除附件后的文档外观(使用上面的脚本)
这是我在删除附件后(使用上面的脚本)添加一个附件后的文档外观
答案 0 :(得分:1)
如果您使用MIME方法附加文件,为什么不使用MIME方法也将其删除?
我使用自己的框架,因此以下代码可能给您留下使事情变得过于复杂的印象,但希望您能从中得到要点:
我有一个枚举,可帮助我浏览各种MIME类型。在这种情况下,您要处理ATTACHMENT
:
public enum MimeContentType {
ATTACHMENT("attachment") {
@Override
public boolean matches(String[] headers) {
int score = 0;
for (String header : headers) {
if (header.startsWith("Content-Disposition")) {
score++;
}
if (header.contains("attachment")) {
score++;
}
if (header.contains("filename")) {
score++;
}
if (score == 3) {
return true;
}
}
return false;
}
},
TEXT("text"),
TEXT_HTML("text/html"),
TEXT_PLAIN("text/plain");
private final String type;
private MimeContentType(String type) {
this.type = type;
}
public boolean matches(String[] headers) {
for (String header : headers) {
if (header.startsWith("Content-Type") && header.contains(type)) {
return true;
}
}
return false;
}
}
然后是一些辅助类:
@FunctionalInterface
public interface ThrowableConsumer<T> extends Consumer<T> {
@Override
default void accept(final T t) {
try {
acceptOrThrow(t);
} catch (final Throwable e) {
throw new RuntimeException(e);
}
}
void acceptOrThrow(T t) throws Throwable;
}
@FunctionalInterface
public interface ThrowableFunction<T, R> extends Function<T, R> {
@Override
default R apply(T t) {
try {
return applyOrThrow(t);
} catch (final Throwable e) {
throw new RuntimeException(e);
}
}
R applyOrThrow(T t) throws Throwable;
}
@FunctionalInterface
public interface ThrowablePredicate<T> extends Predicate<T> {
@Override
default boolean test(T t) {
try {
return testOrThrow(t);
} catch (final Throwable e) {
throw new RuntimeException(e);
}
}
boolean testOrThrow(T t) throws Throwable;
}
@FunctionalInterface
public interface ThrowableSupplier<T> extends Supplier<T> {
@Override
default T get() {
try {
return getOrThrow();
} catch (final Throwable e) {
throw new RuntimeException(e);
}
}
T getOrThrow() throws Throwable;
}
public enum DominoUtil {
;
private static final Vector<String> MIME_FILTERED_HEADERS = new Vector<>();
static {
MIME_FILTERED_HEADERS.add("Content-Type");
MIME_FILTERED_HEADERS.add("Content-Disposition");
}
public static List<MIMEEntity> getMimeEntitiesByContentType(MIMEEntity entity,
MimeContentType contentType) throws NotesException {
Objects.requireNonNull(entity, "Entity cannot be null");
Objects.requireNonNull(contentType, "Content type cannot be null");
List<MIMEEntity> subentities = new ArrayList<>();
MIMEEntity nextEntity = null;
try {
nextEntity = entity.getNextEntity();
while (nextEntity != null) {
String[] entityFilteredHeaders = nextEntity
.getSomeHeaders(MIME_FILTERED_HEADERS, true)
.split("\\n");
if (contentType.matches(entityFilteredHeaders)) {
subentities.add(nextEntity);
}
nextEntity = nextEntity.getNextEntity();
}
} finally {
DominoUtil.recycle(nextEntity);
}
return subentities;
}
public final static MIMEEntity getMimeEntity(Document doc, String itemName,
boolean createOnFail) throws NotesException {
if (itemName == null) {
throw new NullPointerException("Invalid MIME entity item name");
}
MIMEEntity mimeEntity = doc.getMIMEEntity(itemName);
if (mimeEntity == null) {
if (doc.hasItem(itemName)) {
doc.removeItem(itemName);
}
if (createOnFail) {
mimeEntity = doc.createMIMEEntity(itemName);
}
}
return mimeEntity;
}
public static Optional<String> getMimeEntityAttachmentFilename(MIMEEntity entity) throws NotesException {
Objects.requireNonNull(entity, "Entity cannot be null");
return getMimeEntityHeaderValAndParams(
entity, (ThrowablePredicate<MIMEHeader>) h -> h.getHeaderVal().equals("attachment"))
.map(s -> {
Matcher m = Pattern.compile("filename=['\"]?([^'\"\\s]+)").matcher(s);
m.find();
return m.group(1);
});
}
public static Optional<String> getMimeEntityHeaderValAndParams(
MIMEEntity entity, Predicate<MIMEHeader> matcher) throws NotesException {
Objects.requireNonNull(entity, "Entity cannot be null");
Objects.requireNonNull(matcher, "Matcher cannot be null");
Vector<?> headers = entity.getHeaderObjects();
try {
return headers
.stream()
.map(MIMEHeader.class::cast)
.filter(matcher)
.map((ThrowableFunction<MIMEHeader, String>) MIMEHeader::getHeaderValAndParams)
.findFirst();
} finally {
recycle(headers);
}
}
public static void recycle(Base... bases) {
for (Base base : bases) {
if (base != null) {
try {
base.recycle();
} catch (Exception e) {
// Do nothing
}
}
}
}
public static void recycle(Collection<? extends Object> objs) {
objs.stream()
.filter(o -> o instanceof Base)
.map(o -> (Base) o)
.forEach(DominoUtil::recycle);
}
}
最后将完成工作的方法:
public class Example {
public static void yourEntryPoint() {
try {
// The last param is just a way to create an attachment from text
// You have InputStream to pass along obviously
addAttachment(doc, "Body", "fake1.txt", "this is fake text1");
addAttachment(doc, "Body", "fake2.txt", "this is fake text2");
addAttachment(doc, "Body", "fake3.txt", "this is fake text3");
removeAttachment(doc, "Body", "fake2.txt");
removeAttachment(doc, "Body", "fake3.txt");
} catch (NotesException e) {
throw new RuntimeException(e);
}
}
private static void addAttachment(Document doc, String itemName, String fileName, String data)
throws NotesException {
MIMEEntity mimeEntity = null;
Stream stm = null;
try {
mimeEntity = DominoUtil.getMimeEntity(doc, itemName, true);
Optional<MIMEEntity> optAttEntity = getAttachmentMimeEntity(mimeEntity, fileName);
MIMEEntity attachmentEntity = null;
if (optAttEntity.isPresent()) {
attachmentEntity = optAttEntity.get();
} else {
attachmentEntity = mimeEntity.createChildEntity();
MIMEHeader header = attachmentEntity.createHeader("Content-Disposition");
header.setHeaderValAndParams("attachment; filename=\"" + fileName + "\"");
}
stm = doc.getParentDatabase().getParent().createStream();
stm.writeText(data);
attachmentEntity.setContentFromBytes(stm,
"application/octet-stream",
MIMEEntity.ENC_IDENTITY_BINARY);
stm.close();
doc.closeMIMEEntities(true, itemName);
} finally {
DominoUtil.recycle(stm);
DominoUtil.recycle(mimeEntity);
}
}
private static void removeAttachment(Document doc, String itemName, String fileName)
throws NotesException {
MIMEEntity mimeEntity = null;
try {
// Get MIME entity
mimeEntity = DominoUtil.getMimeEntity(doc, itemName, true);
Optional<MIMEEntity> optAttEntity = getAttachmentMimeEntity(mimeEntity, fileName);
if (!optAttEntity.isPresent()) {
return;
}
optAttEntity.get().remove();
// Header cleaning on empty entity
if (mimeEntity.getFirstChildEntity() != null) {
doc.closeMIMEEntities(true, itemName);
} else {
mimeEntity.remove();
}
} finally {
DominoUtil.recycle(mimeEntity);
}
}
private static Optional<MIMEEntity> getAttachmentMimeEntity(MIMEEntity root, String fileName)
throws NotesException {
return DominoUtil
.getMimeEntitiesByContentType(root, MimeContentType.ATTACHMENT)
.stream()
.filter((ThrowablePredicate<MIMEEntity>) mime -> {
Optional<String> opt = DominoUtil.getMimeEntityAttachmentFilename(mime);
return opt.isPresent() && opt.get().equals(fileName);
})
.findFirst();
}
}