由于项目的需要,使用Applet实现文件上传被提上日程,作者关于applet实现文件上传googleN次,baidum次,终于搞定。最大的感触就是网上的资料有时候会误导你,需要不停的做实验,不停地寻找出现问题的解决方案。作者由于几个比较关键的地方网上的资料未提供,在此作为记录,希望能对新手提供一些有用的参考。
关于文件上传的原理,可以baidu一下,网上的资料说得比较明白,在这里略微提一下,文件通过html上传需要设置提交form表单的表单元素的enctype=” multipart/form-data” 原理是,通过为表单元素设置enctype=”multipart/form-data”属性,让表单提交的数据以二进制编码的方式提交,在接收此请求的Servlet中用二进制流来获取内容,就可以取得上传文件的内容,从而实现文件的上传。文件上传后在服务器端得表示如下(选择文本)
当上面文件执行以后会产生如下结果:(选择的上传文件不同,结果类似)

(1) -----------------------------7d45a76025c 
(2) Content-Disposition: form-data; name="text1"; filename=" D:\1.txt" 
(3) Content-Type: text/plain 
(4) 
(5) public static void main(String[] args) { 
(6) FileUtil.makeDir("dir1/dir2/dir3/dir4","c:/java/"); 
(7) } 
(8) } 
(9)
(10) -----------------------------7d45a76025c-- 
其中第一行为分界符,和(10)行一样,第(10)行作为分界符的结尾,注意,比第一行在最后多出两个“-“。第49行为空行,5-8行为需要写入二进制文件或者文本的地方。网上的一些资料没有讲这一部分,需要特别留意。
了解了文件上传的格式,就可以使用applet向服务器端写入以上格式的内容,就可以实现把文件上传到服务器端了。如果服务器端使用Struts2,则框架为我们接收了文件,就不用写servlet了。Struts2可以处理以POST方式提交的数据。下面讲述开发的客户端代码,服务器端的代码如果不清楚,可以参看Struts2的官方文档。
假设系统使用UTF-8编码,客户端调用Applet上传文件的代码
       String url=http://127.0.0.1:8080/upload.action//接收文件的action
       HttpURLConnection con = (HttpURLConnection) new URL(url) .openConnection();//打开连接
String boundary=”-------------------------123456”;//设置的分解符比实际用的少2个“-
String twoHypeLine=” -- “;
String lineEnd=”\r\n”;
con.setDoOutput(true);
conn.setUseCaches(false);
   // Use a post method.POST为大写
        conn.setRequestMethod("POST");
 con.setRequestProperty("Accept", "*/*");
con.setRequestProperty("Accept-Language", "zh-cn");
//设置分隔符
con.setRequestProperty("Content-Type",
                                          "multipart/form-data; boundary="+boundary);
con.setRequestProperty("Accept-Encoding", "gzip, deflate");
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Cache-Control", "no-cache");
              // 设置流式输出的请求头和请求尾
String header =( twoHypeLine + twoHypeLine +boundary+lineEnd+
                            + "Content-Disposition: form-data; name=\"upload\"; filename=\"%s\" " +lineEnd+ "Content-Type: application/octet-stream "+ lineEnd+ lineEnd;
//name属性可以理解为<input type=”file”>中的name属性,在Struts2中被解析为uploadFileName属性
//content-typeStruts2中被解析为UploadContentType
byte[] tailbyte =( lineEnd + twoHypeLine +boundary+ twoHypeLine+ lineEnd) .getBytes();
//文件名种包含中文时,一定要记得使用utf-8
byte[] headByte = String.format(header, file.getName()).getBytes(“utf-8”);
 // 设置请求体的长度(直接输出,避免在本地进行缓存),同时连接服务器
con.setFixedLengthStreamingMode((int) file.length() + headByte.length+ tailbyte.length);
con.connect();
// 写文件流到请求体中
OutputStream dos = con.getOutputStream();
dos.write(headByte); // 写文件头
//file为本地打开的文件
FileInputStream fis = new FileInputStream(file);
int len = 0;
byte b[] = new byte[blockSize];
while (len != -1) {
       len = fis.read(b);
       if (len > 0) {
              dos.write(b, 0, len);
              dos.flush();
              uploadStatus.upload(len);
       }
}
fis.close();
dos.write(tail);
dos.close();
至此文件基本上可以正确的写入到服务器端,那么如何从服务器端读取哪?上传之后的文件可以通过json格式回传数据,在Struts2中只需要设置为返回类型为json即可,
InputStream is = con.getInputStream();
byte[] response = new byte[is.available()];
is.read(response);
JsonObject  jo=new JsonObject(new String(response.getBytes(“UTF-8”));
 
由于回传的数据为UTF-8格式的,必须通过转码才能被JSON对象识别,对于返回的数据,可以做你想做的任何处理,比如在页面上显示等等。当然在上传过程中可以实现进度条。君好运。
参考网站: http://mupload.googlecode.com