Import a BufferedImage into a rich text field

While writing the RSS Importer for XBlog I wanted to be able to grab image files referenced in blog posts being imported and create a new image document for that image. While the importing of RSS Items as new documents is rather straight forward the tough part was getting the image into the rich text field. There are all kinds of how-to type posts on the web for getting an image from a url. But there was nothing useful I could find about importing that downloaded image into a rich text field without writing it to disk. The reason why I didn't want to write the image to disk before importing it is mainly because of permissions. I couldn't be sure that whatever server an XBlog instance was placed on would have permission to write/delete items to disk.

So, let's get this started. The below method is for finding the "img" tag in the html of a post contained in an RSS Feed. This assumes that the tag is defined as an <img> tag and that the first attribute is the src value. We then grab that url from the attribute and pass that along via a list of urls that we can later loop through and import:

	public static List getImageUrls(String html) {
		List urlList = new ArrayList();
		Pattern imgTagRegEx = Pattern.compile("]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>");
		Matcher imgTagMatcher = imgTagRegEx.matcher(html);
		String imgTag = null;
		String imgUrl = null;
		while (imgTagMatcher.find()) {
			imgTag = imgTagMatcher.group();
			if (imgTag != null) {
				Pattern imgSrcRegEx = Pattern.compile("src\\s*=\\s*['\"]([^'\"]+)");
				Matcher imgSrcMatcher = imgSrcRegEx.matcher(imgTag);
				if (imgSrcMatcher.find()) {
					imgUrl = imgSrcMatcher.group();
					if (imgUrl != null) {
						imgUrl = imgUrl.substring(imgUrl.indexOf("\"") + 1);
						urlList.add(imgUrl);
					}
				}
			}
		}
		return urlList;
	}

Next up is a method to actually get the image from the url. It accepts a String parameter for the url:

	public static BufferedImage getImageFile(String url) {
		BufferedImage img = null;
		try {
			URL imgUrl = new URL(url);
			img = ImageIO.read(imgUrl);
			return img;
		} catch (Exception e) {
			System.out.println("Image at url " + url + " not found");
		}
		return null;
	}

The next 2 methods we're actually going to make an assumption here that you've already gotten the BufferedImage from the getImageFile method above and that you want to attach the image to a Rich Text field named imageFile:

	private static void attachImage(Document imageDoc, BufferedImage image, String fileName, String fileExtension) {
		try {
			MIMEEntity mime = imageDoc.createMIMEEntity("imageFile");
			MIMEHeader header = mime.createHeader("Content-Disposition");
			header.setHeaderVal("attachment; filename=\"" + fileName + "\"");
			header = mime.createHeader("Content-ID");
			header.setHeaderVal(fileName);

			byte[] imgByteArray = getImgByteArray(image, fileExtension);
			InputStream is = new ByteArrayInputStream(imgByteArray);
			Stream stream = NotesContext.getCurrent().getCurrentSession().createStream();
			stream.setContents(is);
			mime.setContentFromBytes(stream, "image/" + fileExtension, mime.ENC_IDENTITY_BINARY);
		} catch (NotesException e) {
			e.printStackTrace();
		}
	}

	private static byte[] getImgByteArray(BufferedImage buffImg, String imageExtension) {
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			ImageIO.write(buffImg, imageExtension, baos);
			byte[] imgByteArray = baos.toByteArray();
			return imgByteArray;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

The main issue of importing the image into the rich text field is getting the image into a form that Domino understands which is why we convert it to a "byte[]" that we can then feed to an InputStream. When attempting to figure this out that was the main thing I was having issue with. I was just using an InputStream and not a ByteArrayInputStream. With a lot of help from Nathan Freeman and Jeremy Hodge, Nathan pointed me to an xSnippet from Tony McGuckin which had the missing piece of the puzzle which is where I got that technique in the attachImage method.

I've put together a demo application that shows this in action. It really goes beyond this as it's got almost the entire RSS Importer from XBlog in it to show the technique. But if you download the attachment to this post to look at the code, take a look at the RSSImporter class, that should show you exactly how this is done. You can see this in action on the demo site, or download the attachment and run it on your own server. Hopefully this helps someone out when they want to import an image from a url without the overhead and possible security headaches of writing the file to disk. 

Share This: