From: <asa...@us...> - 2017-05-08 19:22:30
|
Revision: 14419 http://sourceforge.net/p/htmlunit/code/14419 Author: asashour Date: 2017-05-08 19:22:28 +0000 (Mon, 08 May 2017) Log Message: ----------- HtmlImageInput: add .saveAs() Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImage.java trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput2Test.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2017-05-08 08:38:14 UTC (rev 14418) +++ trunk/htmlunit/src/changes/changes.xml 2017-05-08 19:22:28 UTC (rev 14419) @@ -8,6 +8,9 @@ <body> <release version="2.27" date="???" description="GAE broken, Bugfixes"> + <action type="add" dev="asashour" issue="43854916" system="stackoverflow"> + HtmlImageInput: add .saveAs(). + </action> <action type="fix" dev="asashour" issue="1877"> JavaScript: MouseEvent to support .pageX and .pageY for all browsers. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImage.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImage.java 2017-05-08 08:38:14 UTC (rev 14418) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImage.java 2017-05-08 19:22:28 UTC (rev 14419) @@ -595,7 +595,7 @@ * of objects which could all be garbage collected without impacting the ImageReader it is better to * wrap it in another class. */ - private static final class ImageData implements AutoCloseable { + static final class ImageData implements AutoCloseable { private final ImageReader imageReader_; Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput.java 2017-05-08 08:38:14 UTC (rev 14418) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput.java 2017-05-08 19:22:28 UTC (rev 14419) @@ -14,16 +14,27 @@ */ package com.gargoylesoftware.htmlunit.html; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLIMAGE_BLANK_SRC_AS_EMPTY; import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.HTMLIMAGE_NAME_VALUE_PARAMS; +import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_IMAGE_COMPLETE_RETURNS_TRUE_FOR_NO_REQUEST; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.net.URL; import java.util.Map; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import com.gargoylesoftware.htmlunit.ElementNotFoundException; import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.SgmlPage; +import com.gargoylesoftware.htmlunit.WebClient; +import com.gargoylesoftware.htmlunit.WebRequest; +import com.gargoylesoftware.htmlunit.WebResponse; +import com.gargoylesoftware.htmlunit.html.HtmlImage.ImageData; import com.gargoylesoftware.htmlunit.javascript.host.event.Event; import com.gargoylesoftware.htmlunit.util.NameValuePair; @@ -45,6 +56,9 @@ private boolean wasPositionSpecified_; private int xPosition_; private int yPosition_; + private WebResponse imageWebResponse_; + private transient ImageData imageData_; + private boolean downloaded_; /** * Creates an instance. @@ -184,4 +198,52 @@ protected boolean isRequiredSupported() { return false; } + + /** + * <p>Downloads the image contained by this image element.</p> + * <p><span style="color:red">POTENTIAL PERFORMANCE KILLER - DOWNLOADS THE IMAGE - USE AT YOUR OWN RISK</span></p> + * <p>If the image has not already been downloaded, this method triggers a download and caches the image.</p> + * + * @throws IOException if an error occurs while downloading the image + */ + private void downloadImageIfNeeded() throws IOException { + if (!downloaded_) { + // HTMLIMAGE_BLANK_SRC_AS_EMPTY + final String src = getSrcAttribute(); + if (!"".equals(src) + && !(hasFeature(HTMLIMAGE_BLANK_SRC_AS_EMPTY) && StringUtils.isBlank(src))) { + final HtmlPage page = (HtmlPage) getPage(); + final WebClient webclient = page.getWebClient(); + + final URL url = page.getFullyQualifiedUrl(src); + final String accept = webclient.getBrowserVersion().getImgAcceptHeader(); + final WebRequest request = new WebRequest(url, accept); + request.setAdditionalHeader("Referer", page.getUrl().toExternalForm()); + imageWebResponse_ = webclient.loadWebResponse(request); + } + + if (imageData_ != null) { + imageData_.close(); + imageData_ = null; + } + downloaded_ = hasFeature(JS_IMAGE_COMPLETE_RETURNS_TRUE_FOR_NO_REQUEST) + || (imageWebResponse_ != null && imageWebResponse_.getContentType().contains("image")); + } + } + + /** + * Saves this image as the specified file. + * @param file the file to save to + * @throws IOException if an IO error occurs + */ + public void saveAs(final File file) throws IOException { + downloadImageIfNeeded(); + if (null != imageWebResponse_) { + try (InputStream inputStream = imageWebResponse_.getContentAsStream(); + FileOutputStream fileOut = new FileOutputStream(file)) { + IOUtils.copy(imageWebResponse_.getContentAsStream(), fileOut); + } + } + } + } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput2Test.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput2Test.java 2017-05-08 08:38:14 UTC (rev 14418) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/html/HtmlImageInput2Test.java 2017-05-08 19:22:28 UTC (rev 14419) @@ -14,10 +14,16 @@ */ package com.gargoylesoftware.htmlunit.html; +import java.io.File; +import java.io.InputStream; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.junit.Test; import org.junit.runner.RunWith; @@ -96,4 +102,32 @@ assertEquals(expectedPairs, webConnection.getLastParameters()); } + + /** + * @throws Exception if the test fails + */ + @Test + public void saveAs() throws Exception { + try (InputStream is = getClass().getClassLoader(). + getResourceAsStream("testfiles/tiny-jpg.img")) { + final byte[] directBytes = IOUtils.toByteArray(is); + final URL urlImage = new URL(URL_FIRST, "img.jpg"); + final List<NameValuePair> emptyList = Collections.emptyList(); + getMockWebConnection().setResponse(urlImage, directBytes, 200, "ok", "image/jpg", emptyList); + } + + final String html = "<html><head>\n" + + "</head>\n" + + "<body>\n" + + " <input type='image' src='img.jpg' >\n" + + "</body></html>"; + + final HtmlPage page = loadPage(html); + + final HtmlImageInput input = page.querySelector("input"); + final File tempFile = File.createTempFile("img", ".tmp"); + input.saveAs(tempFile); + FileUtils.deleteQuietly(tempFile); + } + } |