研究了一下haXe中的文件上传,因为nme的cpp(neash)库中缺失FileReference类,因此只能采用URLRequest+URLLoader的方式来上传文件。
这里的关键是要请求中采用HTTP协议中标准的multipart/form-data的方式来编码POST数据,这样可以在一次请求中向服务器端提交多个参数,同时上传多个文件,且文件名等信息也包含在请求数据中。
服务器端是很简单的用tomcat6.0和一个jsp页面,使用commons-FileUpload来实现上传。请注意当前版本的FileUpload依赖于commons-IO,从commons.apache.org官网下载这两个库的最新发布jar包并放到tomcat的lib目录下即可。
下面贴代码:
=============== 客户端haXe代码 ================
//要上传的文件路径
#if android
var path = "/data/media/lockscreen/lockscreen_003.jpg";
#else
var path = "D:/tmp/test.jpg";
#end
var idx = path.lastIndexOf("/");
var filename = path.substr(idx + 1); // 不含路径信息的文件名
var upload = new URLRequest("http://192.168.1.88:8080/upload.jsp"); //上传页面地址
upload.method = URLRequestMethod.POST;
upload.contentType = "multipart/form-data; boundary=ABCD"; //此处请参考multipart/form-data编码规范
var data = new ByteArray();
//后面开始编码POST数据,请注意所有的换行符"\r\n"(即CRLF)都是必不可少的
data.writeUTFBytes("--ABCD\r\n");
data.writeUTFBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + filename + "\"\r\n"); // 文件名
data.writeUTFBytes("Content-Type: image/jpeg\r\n"); //文件mime类型
data.writeUTFBytes("\r\n");
data.writeBytes(ByteArray.fromBytes(File.getBytes(path))); // 文件原始数据
data.writeUTFBytes("\r\n");
data.writeUTFBytes("--ABCD\r\n");
data.writeUTFBytes("Content-Disposition: form-data; name=\"test\"\r\n"); // 模拟一个html form中的请求参数
data.writeUTFBytes("\r\n");
data.writeUTFBytes("testValue\r\n"); //参数的值
data.writeUTFBytes("--ABCD--\r\n"); // multipart/form-data结束标志
upload.data = data;
upload.verbose = true;
var uploadLoad = new URLLoader();
uploadLoad.addEventListener(Event.COMPLETE, function(_) { trace("completed, data=" + uploadLoad.data); } );
try {
uploadLoad.load(upload);
} catch (error: SecurityError) {
trace("A SecurityError has occurred.");
}
=============== 服务端jsp代码 ================
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ page contentType="text/html; charset=GBK" language="java" pageEncoding="GBK" %>
<%@ page import="java.io.*, java.util.*, util.*, org.apache.commons.fileupload.*" %>
<%
HashMap map = new HashMap();
try {
DiskFileUpload fu = new DiskFileUpload();
fu.setSizeMax(1024 * 1024 * 4);
fu.setSizeThreshold(4096);
// 设置临时目录:
fu.setRepositoryPath("C:/tmp/");
List fileItems = fu.parseRequest(request);
for (Iterator i = fileItems.iterator(); i.hasNext();) {
FileItem fi = (FileItem) i.next();
String key = fi.getFieldName();
if (fi.isFormField()) {
String val = fi.getString();
map.put(key, val);
} else {
String fileName = fi.getName();
if (fileName == null || fileName.length() == 0) {
continue;
}
fileName = new File(fileName).getName();
File f = new File("C:/upload/", fileName); // 上传文件保存目录
fi.write(f);
}
}
System.out.println("params: " + map);
} catch (Exception e) {
e.printStackTrace();
}
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>test upload</title>
</head>
<body>
<h1>ok, params=<%= map %></h1>
</body>
</html>