这几天做项目遇到一个问题,用java swing做的客户端向服务器批量传输文件,传输量达到200M时会报堆溢出的异常。代码如下:
byte[] content = null;
try {
fin = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] temp = new byte[1024];
int size = 0;
while ((size = fin.read(temp)) != -1) {
out.write(temp, 0, size);
}
fin.close();
content = out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
批量上传是,用循环的方式将每个文件流数组content发送到服务器,把文件名也发送到服务器,服务器再将数组content写入文件。这种方法在文件量较大时java虚拟机奔溃。
我的解决方法是用http的方法上传,依然是做一个循环,代码如下:(点击swing界面上的上传按钮,执行下面的这个线程)
private String serveraddress;
private static String HTTPHEAD = "http://";
private static String HTTPTAIL = ":8080/wms//ReceiveUploadFile";
private String uploadedfilesforlog = "";//记录上传的文件名,用于日志保存
Runnable upload = new Runnable() {
public void run() {
File[] files = fileChooser.getSelectedFiles();
if(files.length>50){
JOptionPane.showMessageDialog(uploadFileDialog.this,"一次上传文件数量不能超过50个");
uploadButton.setEnabled(true);
return;
}
StringBuffer uploadedfiles = new StringBuffer();
if (null == files || files.length == 0) {
JOptionPane.showMessageDialog(uploadFileDialog.this,"您没有选择语音文件,请选择语音文件后上传。");
uploadButton.setEnabled(true);
return;
}
serveraddress = dsclient.getServerAddrss();
for (int i = 0; i < files.length; i++) {
String targetURL = null;// TODO 指定URL
File targetFile = null;// TODO 指定上传文件
targetFile = files[i];
targetURL = HTTPHEAD + serveraddress + HTTPTAIL; // servleturl
PostMethod filePost = new PostMethod(targetURL);
//filePost.getParams().setContentCharset("utf-8");
logger.info(filePost.getParams().getContentCharset());
try {
// 通过以下方法可以模拟页面参数提交
Part[] parts = { new FilePart(targetFile.getName(),targetFile) };
filePost.setRequestEntity(new MultipartRequestEntity(parts,filePost.getParams()));
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
int status = client.executeMethod(filePost);
if (status == HttpStatus.SC_OK) {
if (saveAudioFileToDatabase(files[i]).equals("upload failed")) {
continue;
}
uploadedfilesforlog += uploadedfilesforlog.equals("")?files[i].getName():"," + files[i].getName();
saveLog("success");
logger.info(files[i].getName()+"上传成功");
uploadedfiles.append("[");
uploadedfiles.append(files[i].getName());
uploadedfiles.append("]");
if ((i + 1) % 5 == 0) {
uploadedfiles.append("<BR>");
}
} else {
logger.info("上传失败");
// 上传失败
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
filePost.releaseConnection();
}
}
if (uploadedfiles.length() == 0) {
return;
}
uploadButton.setEnabled(true);
String tip = "<html>语音文件<font color='red'><b>"+ uploadedfiles.toString() + "</b></font>上传成功!</html>";
JOptionPane.showMessageDialog(uploadFileDialog.this, tip);
uploadFileDialog.this.setVisible(false);
uploadFileDialog.this.dispose();
audioFileManagement.loadList();
}
};
服务器短接受代码:
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
public class ReceiveUploadFile extends HttpServlet
{
private static final long serialVersionUID = 1L;
Logger logger = Logger.getLogger(ReceiveUploadFile.class);
private String uploadPath = "/var/lib/X1000/sounds/audiofile/";
private String tempPath = "/var/lib/X1000/sounds/audiofile/buffer/";
File tempPathFile;
public void init()
throws ServletException
{
File uploadFile = new File(this.uploadPath);
if (!(uploadFile.exists()))
uploadFile.mkdirs();
File tempPathFile = new File(this.tempPath);
if (!(tempPathFile.exists()))
tempPathFile.mkdirs();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
DiskFileItemFactory factory;
try
{
factory = new DiskFileItemFactory();
factory.setSizeThreshold(4096);
factory.setRepository(this.tempPathFile);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(41943040L);
List items = upload.parseRequest(request);
Iterator i = items.iterator();
while (i.hasNext())
{
FileItem fi = (FileItem)i.next();
String fileName = fi.getName();
if (fileName != null)
{
String filename = new String(fi.getName().getBytes(), "utf-8");
this.logger.info("=======================接收到语音文件的文件名:" + filename);
File fullFile = new File(filename);
File savedFile = new File(this.uploadPath, fullFile.getName());
fi.write(savedFile);
}
}
System.out.print("upload succeed");
}
catch (Exception e)
{
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
web.xml
<servlet>
<servlet-name>ReceiveUploadFile</servlet-name>
<display-name>ReceiveUploadFile</display-name>
<description>ReceiveUploadFile</description>
<servlet-class>com.gohigh.centrex.common.ReceiveUploadFile</servlet-class>
<load-on-startup>4</load-on-startup>
</servlet>
-<servlet-mapping>
<servlet-name>ReceiveUploadFile</servlet-name>
<url-pattern>/ReceiveUploadFile</url-pattern>
</servlet-mapping>
依赖的jar包:commons-httpclient-3.1.jar,commons-fileupload-1.2.1.jar,commons-codec-1.3.jar,
遇到的问题:中文乱码问题,由于commons-httpclient-3.1.jar包中的默认编码方式不是UTF-8,所以发送到服务器的中文文件名服务器解析乱码。看了好多网上的方法
都是设置编码方式,但是我试了,还是不行,最终只能修改jar包中的源代码了。一个现成的utf-8的jar包下载地址:
另外,修改源码的时候把里面的编码都改成自己想要的编码,这样才确保服务器能正确解析。
http://download.csdn.net/detail/yuanxw44/4028099,这个地址可以下载源码,解压后把里面java目录下的文件拷到eclipse的src目录下即可,需要依赖两个包,
commons-logging.jar和commons-codec.jar,修改后用fatjar重新打一次即可。
commons-httpclient-3.1.jar
commons-fileupload-1.2.1.
commons-fileupload-1.2.1.
commons-codec-1.3.jar