看书上(JSP应用与开发技术)使用JSP文件上传,写了个真无语,压根就有很多问题,上传500KB的文件传过去后只剩350KB,而且编码必须是GBK、GB2312,否则传过去的文件都数据截取不正确。
琢磨了许久,发现问题出在
int startPos = ((file.substring(0,pos)).getBytes()).length;
//取得文件数据的结束的位置
int endPos =((file.substring(0,boundaryLocation)).getBytes()).length;
这里,问题就是根据字符串获取的字节数,然后从字节数组里截取根本就不正确。而后自己实现了个,不用字符串字节,而是自己以字节找字节。如下:
UploadTelRecord.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@page import="java.io.DataInputStream"%> <%@page import="java.io.FileOutputStream"%> <%@page import="java.io.File"%> <%@page import="java.net.URLEncoder" %> <!-- 上传通话录音文件 --> <%! //在字节数组里查找某个字节数组,找到返回>=0,未找到返回-1 private int byteIndexOf(byte[] data,byte[] search,int start) { int index=-1; int len=search.length; for(int i=start,j=0;i<data.length;i++) { int temp=i; j=0; while(data[temp]==search[j]) { System.out.println((j+1)+",值:"+data[temp]+","+search[j]); //计数 j++; temp++; if(j==len) { index=i; return index; } } } return index; } %> <% String getAction=request.getParameter("action"); if(getAction!=null&&(getAction.equals("upload"))) //上传文件 { //定义上传的最大文件字节数1M int MAX_SIZE=1024000; String rootPath; DataInputStream in=null; FileOutputStream fileOut=null; String remoteAddr=request.getRemoteAddr(); String serverName=request.getServerName(); String realPath=request.getRealPath("/"); realPath=realPath.substring(0,realPath.lastIndexOf("\")); //设置保存文件的目录 rootPath=realPath+ "\upload\telRecord\"; //取得客户端上传的数据类型 String contentType=request.getContentType(); try{ if(contentType.indexOf("multipart/form-data")>=0){ in=new DataInputStream(request.getInputStream()); int formDataLength=request.getContentLength(); if(formDataLength>MAX_SIZE) { out.println("0,文件大小超过系统限制!"); out.flush(); return; } //保存上传的文件数据 byte dateBytes[]=new byte[formDataLength]; int byteRead=0; int totalRead=0; while(totalRead<formDataLength) { byteRead=in.read(dateBytes,totalRead,formDataLength); totalRead+=byteRead; } String data=new String(dateBytes,"UTF-8"); //取得上传的文件名 String saveFile=data.substring(data.indexOf("filename="")+10); saveFile=saveFile.substring(0,saveFile.indexOf(" ")); saveFile=saveFile.substring(saveFile.lastIndexOf("\")+1,saveFile.indexOf(""")); //取得数据分割字符串 int lastIndex=contentType.lastIndexOf("="); //数据分割线开始位置boundary=--------------------------- String boundary=contentType.substring(lastIndex+1,contentType.length());//---------------------------257261863525035 //计算开头数据头占用的长度 int startPos; startPos=byteIndexOf(dateBytes,"filename="".getBytes(),0); startPos=byteIndexOf(dateBytes," ".getBytes(),startPos)+1; //遍历掉3个换行符到数据块 startPos=byteIndexOf(dateBytes," ".getBytes(),startPos)+1; startPos=byteIndexOf(dateBytes," ".getBytes(),startPos)+1; //边界位置 int endPos=byteIndexOf(dateBytes,boundary.getBytes(),(dateBytes.length- startPos))-4; //创建文件 String fileName=rootPath+saveFile; File checkFile=new File(fileName); if(checkFile.exists()){ out.println("0,文件已经存在!"); out.flush(); return; } File fileDir=new File(rootPath); if(!fileDir.exists()) fileDir.mkdirs(); //写入文件 fileOut=new FileOutputStream(fileName); fileOut.write(dateBytes,startPos,(endPos-startPos)); fileOut.flush(); out.println("文件上传成功!保存在:"+fileName); } else { out.println("0,未找到上传文件!"); out.flush(); return; } }catch(Exception error) { out.println("发生异常:"+error.getMessage()); } finally { try { if(in!=null) in.close(); if(fileOut!=null) fileOut.close(); }catch(Exception e ){} } out.println("<br><br>"); out.println("<a href='UploadTelRecord.jsp'>继续上传</a>"); return; } %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>上传通话记录</title> </head> <body style="margin:50px;"> <p>请选择您要上传的通话录音文件,文件命名格式为:通话时间_手机号_联系人姓名.后缀,没有联系人姓名请置空,如: 111213123123_10086_中国移动.amr,没有姓名则为111213123123_10086_.amr</p> <form method="POST" action="UploadTelRecord.jsp?action=upload" ENCTYPE="multipart/form-data"> <input type="file" name="file1" size="30"><br/> <input type="submit" value="开始上传"> </form> </body> </html>