diff --git a/activeweb-testing/src/test/java/app/controllers/UploadController.java b/activeweb-testing/src/test/java/app/controllers/UploadController.java index f6ffcc83f..6be825a7c 100644 --- a/activeweb-testing/src/test/java/app/controllers/UploadController.java +++ b/activeweb-testing/src/test/java/app/controllers/UploadController.java @@ -19,11 +19,10 @@ import org.javalite.activeweb.AppController; import org.javalite.activeweb.FileItem; import org.javalite.activeweb.FormItem; +import org.javalite.activeweb.MultipartForm; import org.javalite.activeweb.annotations.POST; import org.javalite.common.Util; -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -35,6 +34,7 @@ * @author Igor Polevoy */ public class UploadController extends AppController { + @POST public void save(){ view("content", new String(uploadedFiles().next().getBytes())); @@ -98,13 +98,19 @@ public void paramValues(){ } @POST - public void getFile() throws IOException { + public void getFile() { FileItem file = getFile("file", multipartFormItems()); respond(file.getStreamAsString()); } @POST - public void multipleArguments() throws IOException { + public void multipleArguments() { respond(param("first_name", multipartFormItems()) + " " + param("last_name", multipartFormItems())); } + + @POST + public void useMultiPartFormAPI(){ + MultipartForm form = multipartForm(); + respond(form.getFileItems().get(0).getStreamAsString() + " " + form.param("name") ); + } } diff --git a/activeweb-testing/src/test/java/org/javalite/activeweb/UploadControllerSpec.java b/activeweb-testing/src/test/java/org/javalite/activeweb/UploadControllerSpec.java index 7e41e0fa3..7fc8ac787 100644 --- a/activeweb-testing/src/test/java/org/javalite/activeweb/UploadControllerSpec.java +++ b/activeweb-testing/src/test/java/org/javalite/activeweb/UploadControllerSpec.java @@ -160,4 +160,14 @@ public void shouldSendMultipleArguments(){ .post("multiple-arguments"); a(responseContent()).shouldBeEqual("John Doe"); } + + @Test + public void shouldUseMultiPartFormAPI(){ + controller("upload") + .contentType("multipart/form-data") + .formItem(new FileItem("hello.txt", "file", "text/plain", "hello".getBytes())) + .formItem("name", "John") + .post("Use-Multi-Part-Form-API"); + a(responseContent()).shouldBeEqual("hello John"); + } } diff --git a/activeweb/src/main/java/org/javalite/activeweb/HttpSupport.java b/activeweb/src/main/java/org/javalite/activeweb/HttpSupport.java index 28edd46a3..7747ea530 100644 --- a/activeweb/src/main/java/org/javalite/activeweb/HttpSupport.java +++ b/activeweb/src/main/java/org/javalite/activeweb/HttpSupport.java @@ -816,6 +816,33 @@ protected List multipartFormItems(String encoding) { return multipartFormItems(encoding, Configuration.getMaxUploadSize()); } + + /** + * @return {@link MultipartForm} object for convenience. + */ + protected MultipartForm multipartForm(){ + return multipartForm("UTF-8", Configuration.getMaxUploadSize()); + } + + /** + * @param encoding encoding to use to read values from request + * @param maxUploadSize set max upload size + * + * @return {@link MultipartForm} object for convenience. + */ + protected MultipartForm multipartForm(String encoding, long maxUploadSize){ + MultipartForm multipartForm = new MultipartForm(); + List formItems = multipartFormItems(encoding, maxUploadSize); + for (FormItem formItem : formItems) { + if(formItem instanceof org.javalite.activeweb.FileItem){ + multipartForm.addFileItem((org.javalite.activeweb.FileItem) formItem); + }else { + multipartForm.addFormItem(formItem); + } + } + return multipartForm; + } + /** * Returns a collection of uploaded files and form fields from a multi-part request. * This method uses DiskFileItemFactory. diff --git a/activeweb/src/main/java/org/javalite/activeweb/MultipartForm.java b/activeweb/src/main/java/org/javalite/activeweb/MultipartForm.java new file mode 100644 index 000000000..3d90c8d40 --- /dev/null +++ b/activeweb/src/main/java/org/javalite/activeweb/MultipartForm.java @@ -0,0 +1,59 @@ +package org.javalite.activeweb; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MultipartForm { + + private List formItems = new ArrayList<>(); + private List fileItems = new ArrayList<>(); + + void addFormItem(FormItem formItem){ + formItems.add(formItem); + } + + void addFileItem(FileItem fileItem){ + fileItems.add(fileItem); + } + + /** + * @return all file items + */ + public List getFileItems() { + return fileItems; + } + + /** + * @return all form items + */ + public List getFormItems() { + return formItems; + } + + /** + * + * @param name name of a form input that is not a file + * @return value of a named input from a form + */ + public String param(String name){ + for (FormItem formItem : formItems) { + if(formItem.getFieldName().equals(name)){ + return formItem.getStreamAsString(); + } + } + return null; + } + + /** + * @return all form items that are not files. + */ + public Map params(){ + Map map = new HashMap<>(); + for (FormItem formItem : formItems) { + map.put(formItem.getFieldName(), formItem.getStreamAsString()); + } + return map; + } +} diff --git a/activeweb/src/test/java/org/javalite/activeweb/freemarker/RenderTagSpec.java b/activeweb/src/test/java/org/javalite/activeweb/freemarker/RenderTagSpec.java index 17a472d06..3fec47ccb 100644 --- a/activeweb/src/test/java/org/javalite/activeweb/freemarker/RenderTagSpec.java +++ b/activeweb/src/test/java/org/javalite/activeweb/freemarker/RenderTagSpec.java @@ -42,13 +42,13 @@ public void before() throws IOException { } @Test(expected = ViewException.class) - public void shouldThrowExceptionIfPartialAttributeMissing() throws IOException, TemplateException { + public void shouldThrowExceptionIfPartialAttributeMissing() { StringWriter sw = new StringWriter(); manager.merge(new HashMap(), "/partial/main_missing_partial_attribute", sw); } @Test - public void shouldRenderPartialRelativeToContainerTemplate() throws IOException, TemplateException { + public void shouldRenderPartialRelativeToContainerTemplate() { StringWriter sw = new StringWriter(); manager.merge(map("fruit", "apple"), "/partial/main_with_simple_partial", sw); @@ -56,7 +56,7 @@ public void shouldRenderPartialRelativeToContainerTemplate() throws IOException, } @Test - public void shouldRenderSharedPartial() throws IOException, TemplateException { + public void shouldRenderSharedPartial() { StringWriter sw = new StringWriter(); manager.merge(map("fruit", "apple"), "/partial/main_with_shared_partial", sw); @@ -65,7 +65,7 @@ public void shouldRenderSharedPartial() throws IOException, TemplateException { @Test(expected = ViewException.class) - public void shouldRejectIncorrectlyNamedSharedPartial() throws IOException, TemplateException { + public void shouldRejectIncorrectlyNamedSharedPartial() { StringWriter sw = new StringWriter(); manager.merge(map("fruit", "apple"), "/partial/main_with_incorrectly_named_shared_partial", sw); @@ -74,14 +74,14 @@ public void shouldRejectIncorrectlyNamedSharedPartial() throws IOException, Temp } @Test - public void shouldRenderPartialWithCollection() throws IOException, TemplateException { + public void shouldRenderPartialWithCollection() { StringWriter sw = new StringWriter(); manager.merge(map("fruits", li("apple", "prune", "pear")), "/partial/main_with_collection_partial", sw); a(sw.toString()).shouldBeEqual("and the fruit is: apple and the fruit is: prune and the fruit is: pear "); } @Test - public void shouldRenderPartialWithCollectionAndCounter() throws IOException, TemplateException { + public void shouldRenderPartialWithCollectionAndCounter() { StringWriter sw = new StringWriter(); manager.merge(map("fruits", li("apple", "prune", "pear")), "/partial/main_with_collection_partial_and_counter", sw); a(sw.toString()).shouldBeEqual("and the fruit is: apple and the count is: 0 " + @@ -90,7 +90,7 @@ public void shouldRenderPartialWithCollectionAndCounter() throws IOException, Te } @Test - public void shouldRenderSharedPartialWithCollection() throws IOException, TemplateException { + public void shouldRenderSharedPartialWithCollection(){ StringWriter sw = new StringWriter(); manager.merge(map("fruits", li("apple", "prune", "pear")), "/partial/main_with_shared_collection_partial", sw); @@ -98,7 +98,7 @@ public void shouldRenderSharedPartialWithCollection() throws IOException, Templa } @Test - public void shouldRenderSpacerWithCollectionPartial() throws IOException, TemplateException { + public void shouldRenderSpacerWithCollectionPartial(){ StringWriter sw = new StringWriter(); manager.merge(map("fruits", li("apple", "prune", "pear")), "/partial/main_with_collection_partial_and_spacer", sw); a(sw.toString()).shouldBeEqual("and the fruit is: apple " + @@ -109,14 +109,14 @@ public void shouldRenderSpacerWithCollectionPartial() throws IOException, Templa } @Test - public void shouldPassSimpleParameterToPartial() throws IOException, TemplateException { + public void shouldPassSimpleParameterToPartial(){ StringWriter sw = new StringWriter(); manager.merge(map("fruit_name", "pear"), "/partial/main_with_simple_partial_and_parameter", sw); a(sw.toString()).shouldEqual("and the fruit name is: pear"); } @Test - public void shouldPassSimpleParameterToPartialWithCollection() throws IOException, TemplateException { + public void shouldPassSimpleParameterToPartialWithCollection(){ StringWriter sw = new StringWriter(); manager.merge(map("fruits", li("apple", "prune", "pear")), "/partial/main_with_collection_and_simple_parameters_for_partial", sw); a(sw.toString()).shouldEqual("and the fruit is: apple, berry: blueberry " + @@ -126,15 +126,11 @@ public void shouldPassSimpleParameterToPartialWithCollection() throws IOExceptio @Test - public void shouldCheckFirstAndLastWithCollection() throws IOException, TemplateException { + public void shouldCheckFirstAndLastWithCollection(){ StringWriter sw = new StringWriter(); manager.merge(map("fruits", li("apple", "prune", "pear")), "/partial/main_with_collection_partial_with_first_and_last", sw); a(sw.toString()).shouldBeEqual( "and the fruit is: apple, first: true, last: false " + "and the fruit is: prune, first: false, last: false " + "and the fruit is: pear, first: false, last: true"); } - - - - }