Created
April 8, 2009 15:27
-
-
Save ymnk/91826 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.{ByteArrayOutputStream, IOException, OutputStream, File} | |
import java.io.{File, FileInputStream, DataInputStream} | |
import java.net.{URL, URLConnection, HttpURLConnection} | |
import java.util.Random | |
abstract sealed class Param | |
case class FieldParam(key:String, value:String) extends Param | |
case class DataParam(key:String, filename:String, | |
data:Array[Byte], typ:Option[String]) extends Param | |
case class FileParam(key:String, file:File, typ:Option[String]) extends Param | |
object PostMultiPartFormData { | |
private lazy val boundary:Array[Byte] = { | |
val chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
val rand = new Random() | |
(0 until 10).foldLeft(new StringBuilder){ | |
case (b, _) => b.append(chars(rand.nextInt(chars.length))) | |
}.toString.getBytes | |
} | |
def apply(url:String, param:Param*):Option[String] = { | |
try{ | |
val con = new URL(url).openConnection match{ | |
case con:HttpURLConnection => con | |
case _ => throw new Exception | |
} | |
con.setUseCaches(false) | |
con.setDoOutput(true) | |
con.setRequestProperty("Content-Type", | |
"multipart/form-data; boundary=%s".format(new String(boundary))) | |
implicit val baos = new ByteArrayOutputStream | |
param foreach { | |
case FieldParam(k, v) => writeField(k, v) | |
case DataParam(k, f, d, t) => writeData(k, f, d, t) | |
case FileParam(k, f, t) => | |
val data = new Array[Byte](f.length.asInstanceOf[Int]) | |
new DataInputStream(new FileInputStream(f)) match{ | |
case i => i.readFully(data); i.close | |
} | |
writeData(k, f.getName, data, t) | |
} | |
writeEnd | |
baos.flush | |
baos.close | |
con.setRequestProperty("Content-Length", baos.size.toString) | |
con.getOutputStream match{ | |
case cout => | |
baos.writeTo(cout) | |
cout.close | |
} | |
con.getResponseCode match{ | |
case code if code!=200 => None | |
case _ => | |
val result = new StringBuilder | |
con.getInputStream match{ | |
case in => | |
for(c <- Stream.const(in.read _).map(_()).takeWhile(_ != -1)) | |
result.append(c.toChar) | |
in.close | |
} | |
Some(result.toString) | |
} | |
} | |
catch{ | |
case ioe => return None | |
} | |
} | |
private val CRLF = "\r\n".getBytes | |
private val -- = "--".getBytes | |
private val cd = "Content-Disposition: form-data; name=\"%s\"" | |
private def writeField(k:String, v:String)(implicit b:OutputStream){ | |
write(--, boundary, CRLF) | |
write(cd.format(k).getBytes, CRLF) | |
write(CRLF) | |
write(v.getBytes, CRLF) | |
} | |
private val cdf = "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"" | |
private val ct = "Content-Type: %s" | |
private val os = "application/octet-stream" | |
private def writeData(k:String, f:String, d:Array[Byte], t:Option[String]) | |
(implicit b:OutputStream){ | |
val typ = (t getOrElse os) | |
write(--, boundary, CRLF) | |
write(cdf.format(k, f).getBytes, CRLF) | |
write(ct.format(typ).getBytes, CRLF) | |
write(CRLF) | |
write(d, CRLF) | |
} | |
private def writeEnd(implicit b:OutputStream){ | |
write(--, boundary, --, CRLF) | |
} | |
private def write(data:Array[Byte]*)(implicit b:OutputStream){ | |
data.foreach(b.write(_)) | |
} | |
} | |
/* | |
object Test { | |
def main(arg:Array[String]){ | |
import java.io._ | |
val f = new File(arg(0)) | |
val data = new Array[Byte](f.length.asInstanceOf[Int]) | |
new DataInputStream(new FileInputStream(f)) match{ | |
case fis => fis.readFully(data); fis.close | |
} | |
val result = | |
PostMultiPartFormData("http://127.0.0.1/post", | |
FieldParam("MAX_FILE_SIZE", "1000"), | |
// FileParam("upload", f, None), | |
DataParam("upload", arg(0), data, None)) | |
println(result getOrElse "error") | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment