有没有人试过通过程序同时上传多个文件的?

e9876 2013-10-21 04:36:56
假设我的电脑上有一些文件,是通过程序自动生成的,
然后我希望能在需要的时候利用程序将这些文件传到服务器端(服务器端我有增删改文件的权限)
我想用HttpClient4模仿网页的multipart/form-data来上传,但是总是出问题。
希望各位高手能帮忙看看,万分感谢。

本地(客户端)代码:
Test.java

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.fang.util.UploadUtil;

/**
* @time 2013-10-21
*/
public class Test {
public static void main(String[] args){
List<File> filelist = new ArrayList<File>();
filelist.add(new File("c:\\aaa.jpg"));
filelist.add(new File("c:\\bbb.txt"));
//filelist.add(new File("c:\\ccc.avi"));

DefaultHttpClient client = new DefaultHttpClient();

HttpPost post = new HttpPost("http://localhost:8080/test.jsp");

UploadUtil.upload(post, filelist);

try {
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
entity.consumeContent();
} catch (Exception e) {
e.printStackTrace();
}
}
}


UploadUtil.java

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;

/**
* @time 2013-10-21
*/
public class UploadUtil {

private static Log log = LogFactory.getLog(UploadUtil.class);

public static void upload(HttpPost post,List<File> files){

String boundary = "---------------------------test";

post.addHeader("Content-Type", "multipart/form-data; boundary="+boundary);

ByteArrayOutputStream os = new ByteArrayOutputStream();

try {

String fullBoundary = "\r\n--"+boundary + "\r\n";



for(File file : files){
os.write(fullBoundary.getBytes());
os.write("Content-Disposition: form-data; name=\"uploadFile\"; filename=\"".getBytes());
os.write(file.getName().getBytes());
os.write("\"\r\n".getBytes());
FileInputStream fis = new FileInputStream(file);
byte[] b = new byte[1024];
int total = 0;
int length = 0;
while((length=fis.read(b))!=-1){
os.write(b, 0, length);
total += length;
}

System.out.println("File name:"+file.getName());
System.out.println("File size:"+total);
System.out.println("================");

fis.close();
os.write("\r\n".getBytes());
}

ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());

HttpEntity entity = new InputStreamEntity(is , is.available());
post.setEntity(entity);
} catch (IOException e) {
log.error("设置上传的文件时出错",e);
}
}
}


服务器端:
test.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@page import="org.apache.commons.fileupload.servlet.*"%>
<%@page import="org.apache.commons.fileupload.disk.*"%>
<%@page import="org.apache.commons.fileupload.*"%>
<%

boolean isMultipart = ServletFileUpload.isMultipartContent(req);

System.out.println(isMultipart);

if(isMultipart){
try {
DiskFileItemFactory factory=new DiskFileItemFactory();
factory.setSizeThreshold(1024*1024*2);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(fileSize!=null?fileSize:1024*1024*10);
upload.setSizeMax(-1);
upload.setHeaderEncoding("UTF-8");
List<FileItem> itemlist = upload.parseRequest(req);
for(FileItem item:itemlist){
System.out.println(item.getFieldName()+":"+item.getName()+":"+item.getSize());
}
} catch (FileUploadException e) {
e.printStackTrace();
}

}
%>


出现的异常为:

org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:381)
at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)


希望有经验的各位能帮忙看一下
...全文
12300 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
e9876 2013-10-22
  • 打赏
  • 举报
回复
多谢12L,搞定了。 对照了你的代码, 原来只是Content-Type后面少了一个\r\n 无语死了。
suciver 2013-10-22
  • 打赏
  • 举报
回复
做过这样的例子不过用的是jdk原生的HttpURLConnection。后台用的是struts2的action不过struts2的文件解析也是用commons-fileUpload的。传文件的代码是这样的

public class HttpURLConnectionUploadFileTest {
	private static DataOutputStream ds;//用数据输出流可以直接writeBytes字符串
	private static String boundary = "****";//分隔符随意
	public static void main(String[] args) throws Exception {
		HttpURLConnection conn = (HttpURLConnection) new URL(
				"http://localhost:8080/Demo/fileUpload.action")
				.openConnection();
		setConnection(boundary, conn);   
		ds=new DataOutputStream(conn.getOutputStream());
//这里就是测试连续上传文件,我这里是用for循环传同一个文件楼主可以多次调用writeFile传//不同的文件
		for(int i=0;i<4;i++){
		   writeFile(new File("e:/","ReplayParser.exe"),"files");
                }
		ds.writeBytes("--" + boundary + "--\r\n");
		ds.flush();
		ds.close();
		conn.disconnect();
	}
//这个是写文件的,根据浏览器传文件时的网络数据完全模拟一样的输出到服务端
	private static void writeFile(File file,String inputName)
			throws IOException, FileNotFoundException {
		String fileName=URLEncoder.encode(file.getName(),"utf-8");
		ds.writeBytes("--" + boundary + "\r\n");
		ds.writeBytes("Content-Disposition: form-data; name=\""+inputName+"\"; filename=\""+fileName+"\"\r\n");
		ds.writeBytes("Content-Type: "+URLConnection.guessContentTypeFromName(fileName)+"\r\n\r\n");
		FileInputStream fis=new FileInputStream(file);
		byte[] b=new byte[1024];
		int i=-1;
		while((i=fis.read(b))!=-1){
			ds.write(b, 0, i);
		}
		ds.writeBytes("\r\n");
		fis.close();
	}
	private static void setConnection(String boundary, HttpURLConnection conn)
			throws ProtocolException {
		conn.setDoOutput(true);
		conn.setUseCaches(false);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Charset", "UTF-8"); 
		conn.setRequestProperty("Content-Type","multipart/form-data; boundary=" + boundary);
		/**
		 *  告诉HttpUrlConnection,我们需要采用流方式上传数据,无需本地缓存数据。
		 *  HttpUrlConnection默认是将所有数据读到本地缓存,然后再发送给服务器,
		 *  这样上传大文件时就会导致内存溢出。   
		 */
		conn.setChunkedStreamingMode(1024);//这句话传文件时很重要
	}
}
后台用的是struts2的当然楼主也可以换成你的commons-fileUpload的写法,struts2的内部也是用commons-fileUpload所以struts2能上传成功commons-fileUpload也是一样可以的

public class FileUploadAction extends ActionSupport {
	private List<File> files;
	private List<String> filesFileName;

	@Override
	public String execute() throws Exception {
		for(int i=0;i<files.size();i++){
			files.get(i).renameTo(new File("F:/",i+filesFileName.get(i)));
		}
		return SUCCESS;
	}
	

	public List<File> getFiles() {
		return files;
	}

	public void setFiles(List<File> files) {
		this.files = files;
	}

	public List<String> getFilesFileName() {
		return filesFileName;
	}

}
e9876 2013-10-22
  • 打赏
  • 举报
回复
顶一下吧,感觉下班以后论坛都没人了。。
Defonds 2013-10-21
  • 打赏
  • 举报
回复
引用 8 楼 e9876 的回复:
[quote=引用 7 楼 defonds 的回复:] 这里有例子: Java 文件分块上传客户端源代码 Java 文件分块上传服务器端源代码
很感谢,不过您搞错了, 这个程序不是把一个文件分块上传, 而是模仿一个multipart/form-data的form同时上传几个文件,然后在服务器端接收。。[/quote]客气了。 给你的例子也是这样的,只不过是分成多块。你可以无视多块业务,单看一块怎么处理的。
e9876 2013-10-21
  • 打赏
  • 举报
回复
引用 7 楼 defonds 的回复:
这里有例子: Java 文件分块上传客户端源代码 Java 文件分块上传服务器端源代码
很感谢,不过您搞错了, 这个程序不是把一个文件分块上传, 而是模仿一个multipart/form-data的form同时上传几个文件,然后在服务器端接收。。
e9876 2013-10-21
  • 打赏
  • 举报
回复
引用 4 楼 u012463264 的回复:
你说总是出现问题 ,能说说具体是什么问题吗
就是后面抛出的异常。
e9876 2013-10-21
  • 打赏
  • 举报
回复
我把

String fullBoundary = "\r\n--"+boundary + "\r\n";
修改为

String fullBoundary = "\r\n--"+boundary;
后, 异常不抛了,但是服务器端还是没办法接收到文件。 List<FileItem> itemlist 的 size为 0
别闹腰不好 2013-10-21
  • 打赏
  • 举报
回复
你说总是出现问题 ,能说说具体是什么问题吗
e9876 2013-10-21
  • 打赏
  • 举报
回复
引用 2 楼 huxiweng 的回复:
fis.close(); 注释掉试试
无任何效果。
teemai 2013-10-21
  • 打赏
  • 举报
回复
fis.close(); 注释掉试试
e9876 2013-10-21
  • 打赏
  • 举报
回复
对了,这个是我写这段程序时参考的网页。 http://www.pc6.com/infoview/Article_50285.html 希望高手们能抽空看看,解决一下小弟的问题,谢谢了

81,091

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧