如何正确添加和删除MIME附件

时间:2018-11-22 12:51:11

标签: xpages attachment mime

我正在将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项的大小均正确

enter image description here

这是我删除附件后的文档外观(使用上面的脚本)

enter image description here

这是我在删除附件后(使用上面的脚本)添加一个附件后的文档外观

enter image description here

  • 添加或删除附件时我可以做错什么吗? (看到 脚本)
  • “正文”字段是否具有“商店”似乎并不重要 内容是否设置为MIME”选项
  • 另请参阅此问题 How to Add and Remove attachments using MIME

1 个答案:

答案 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();
    }

}