changeset 1274:383f924dfe9d

support multipart files in http request
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 04 Dec 2018 06:08:20 -0700
parents ed6e8bd78c11
children cc3dabc05f72
files src/luan/modules/url/MultipartClient.java src/luan/webserver/Request.java
diffstat 2 files changed, 49 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/luan/modules/url/MultipartClient.java	Tue Dec 04 03:35:38 2018 -0700
+++ b/src/luan/modules/url/MultipartClient.java	Tue Dec 04 06:08:20 2018 -0700
@@ -9,6 +9,7 @@
 import java.util.HashMap;
 import luan.LuanTable;
 import luan.LuanException;
+import luan.webserver.Request;
 
 
 public final class MultipartClient {
@@ -18,6 +19,20 @@
 
 	private final Map params = new HashMap();
 
+	private static Object get(Map<Object,Object> params,String key) throws LuanException {
+		Object val = params.remove(key);
+		if( val==null)
+			throw new LuanException( "parameter '"+key+"' is required in multipart file" );
+		return val;
+	}
+
+	private static String getString(Map<Object,Object> params,String key) throws LuanException {
+		Object val = get(params,key);
+		if( !(val instanceof String) )
+			throw new LuanException( "parameter '"+key+"' must be a string" );
+		return (String)val;
+	}
+
 	MultipartClient(Map params) throws LuanException {
 		for( Object hack : params.entrySet() ) {
 			Map.Entry entry = (Map.Entry)hack;
@@ -26,17 +41,26 @@
 			List list = new ArrayList();
 			if( val instanceof String ) {
 				list.add(val);
-			} else {
-				if( !(val instanceof LuanTable) )
-					throw new LuanException( "parameter '"+key+"' must be string or table" );
+			} else if(val instanceof LuanTable) {
 				LuanTable t = (LuanTable)val;
-				if( !t.isList() )
-					throw new LuanException( "parameter '"+key+"' table must be list" );
-				for( Object obj : t.asList() ) {
-					if( !(obj instanceof String) )
-						throw new LuanException( "parameter '"+key+"' values must be strings" );
-					list.add(obj);
+				if( t.isList() ) {
+					for( Object obj : t.asList() ) {
+						if( obj instanceof String ) {
+							list.add(obj);
+						} else
+							throw new LuanException( "parameter '"+key+"' values must be strings or tables" );
+					}
+				} else {
+					Map<Object,Object> map = t.asMap();
+					String filename = getString(map,"filename");
+					String contentType = getString(map,"content_type");
+					Object content = get(map,"content");
+					if( !(content instanceof String || content instanceof byte[]) )
+						throw new LuanException( "content must be a string or binary" );
+					list.add( new Request.MultipartFile(filename,contentType,content) );
 				}
+			} else {
+				throw new LuanException( "parameter '"+key+"' must be string or table" );
 			}
 			this.params.put(key,list);
 		}
@@ -53,14 +77,25 @@
 			String name = (String)entry.getKey();
 			List list = (List)entry.getValue();
 			for( Object obj : list ) {
-				String val = (String)obj;
 		        out.write(__DASHDASH);
 		        out.write(boundaryBytes);
 		        out.write(__CRLF);
 	            out.write(("Content-Disposition: form-data; name=\""+name+"\"").getBytes(__ISO_8859_1));
-	            out.write(__CRLF);
-		        out.write(__CRLF);
-				out.write(val.getBytes());
+				if( obj instanceof String ) {
+					String val = (String)obj;
+		            out.write(__CRLF);
+			        out.write(__CRLF);
+					out.write(val.getBytes());
+				} else {
+					Request.MultipartFile mpf = (Request.MultipartFile)obj;
+		            out.write(("; filename=\""+mpf.filename+"\"").getBytes(__ISO_8859_1));
+		            out.write(__CRLF);
+		            out.write(("Content-Type: "+mpf.contentType).getBytes(__ISO_8859_1));
+		            out.write(__CRLF);
+			        out.write(__CRLF);
+					byte[] content = mpf.content instanceof String ? ((String)mpf.content).getBytes() : (byte[])mpf.content;
+					out.write(content);
+				}
 		        out.write(__CRLF);
 			}
 		}
--- a/src/luan/webserver/Request.java	Tue Dec 04 03:35:38 2018 -0700
+++ b/src/luan/webserver/Request.java	Tue Dec 04 06:08:20 2018 -0700
@@ -22,7 +22,7 @@
 		public final String contentType;
 		public final Object content;  // byte[] or String
 
-		MultipartFile(String filename,String contentType,Object content) {
+		public MultipartFile(String filename,String contentType,Object content) {
 			this.filename = filename;
 			this.contentType = contentType;
 			this.content = content;