Android文件上传-本地+服务器一条龙分析

本地:

先看下项目结构

MainActivity.java

package com.huxq.uploadexample;

import java.io.File;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity implements OnUploadListener {
	// 服务器路径,换成自己的
	private String urlString = "http://192.168.1.2:8080/UploadTest/Upload";
	/**
	 * 上传文件的路径
	 */
	String filePath;
	/**
	 * 上传的文件名
	 */
	String fileName;
	ProgressDialog dialog;
	/**
	 * 在读取文件流的时候,同一进度会多次回调,通过这个标记,只有在进度更新的情况下才会更新ui 节省资源
	 */
	int oldProcess;

	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			Log.i("process", "process" + msg.arg1);
			dialog.setProgress(msg.arg1);
			// 第一次没有显示dialog的时候显示dialog
			if (!dialog.isShowing()) {
				Log.i("process", "show");
				dialog.show();
			} else {
				if (msg.arg1 == 100) {// 提示用户上传完成
					dialog.dismiss();
					toast("上传完成!");
				}
			}
		};
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initProgressDialog();
	}

	public void upLoad(View v) {
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			// toast("上传");
			String sdcardPath = Environment.getExternalStorageDirectory()
					.getAbsolutePath();
			filePath = sdcardPath + "/Abook/";
			File file = new File(filePath);
			// 这里我选的是Abook文件夹下第五个文件上传,得根据自己的实际情况来,否则肯定出错。
			fileName = file.list()[4];
			filePath += fileName;
			Log.i("file.size", "size=" + file.list().length + "filePath"
					+ filePath);
		} else {
			toast("没有内存卡");
			return;
		}
		new Thread() {
			public void run() {
				try {
					String response = HttpUtil.sendFile(urlString, filePath,
							fileName, MainActivity.this);
					Log.i("response", "response" + response);
				} catch (Exception e) {
					e.printStackTrace();
				}
			};
		}.start();
	}

	@Override
	public void onUpload(double process) {
		process = process * 100;
		int currentProcess = (int) process;
		dialog.setProgress(currentProcess);
		// 避免重复发消息,可以把if给去掉看看会发生什么
		if (currentProcess > oldProcess) {
			Message msg = handler.obtainMessage();
			msg.arg1 = (int) process;
			handler.sendMessage(msg);
		}
		oldProcess = currentProcess;
	}

	public void initProgressDialog() {
		dialog = new ProgressDialog(this);
		dialog.setMax(100);
		dialog.setProgress(0);
		dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		dialog.setCancelable(false);
		dialog.setCanceledOnTouchOutside(false);
		dialog.setTitle("正在努力上传...");
	}

	public void toast(String text) {
		Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT)
				.show();
	}

}

HttpUtil.java

public static String sendFile(String urlPath, String filePath,
			String newName,OnUploadListener listener) throws Exception {
		String end = "\r\n";
		String twoHyphens = "--";
		String boundary = "******";

		URL url = new URL(urlPath);
		HttpURLConnection con = (HttpURLConnection) url.openConnection();
		//下载需要将setDoInput方法的参数值设为true
		con.setDoInput(true);
		//上传需要将setDoOutput方法的参数值设为true
		con.setDoOutput(true);
		//禁止HttpURLConnection使用缓存
		con.setUseCaches(false);
		//使用POST请求,必须大写
		con.setRequestMethod("POST");
		//以下三行设置http请求头信息
		con.setRequestProperty("Connection", "Keep-Alive");
		con.setRequestProperty("Charset", "UTF-8");
		//在模拟web页面向服务器端上传文件时,每个文件的开头需要有一个分界符,
		//分界符需要在http请求头中指定。boundary是任意一个字符串,一般为******
		con.setRequestProperty("Content-Type", "multipart/form-data;boundary="
				+ boundary);

		DataOutputStream ds = new DataOutputStream(con.getOutputStream());

		ds.writeBytes(twoHyphens + boundary + end);
		//上传文件相关信息,这些信息包括请求参数名,上传文件名,文件类型,但并不限于此
		ds.writeBytes("Content-Disposition: form-data; "
				+ "name=\"file1\";filename=\"" + newName + "\"" + end);
		ds.writeBytes(end);

		//获得文件的输入流,通过流传输文件。在这里我重写了FileInputStream,为了监听上传进度
		CustomFileInputStream fStream = new CustomFileInputStream(filePath);
		fStream.setOnUploadListener(listener);
		/* 设置每次写入1024bytes */
		int bufferSize = 1024;
		byte[] buffer = new byte[bufferSize];

		int length = -1;
		// 从文件读取数据至缓冲区
		while ((length = fStream.read(buffer)) != -1) {
			//将资料写入DataOutputStream中
			ds.write(buffer, 0, length);
		}
		ds.writeBytes(end);
		ds.writeBytes(twoHyphens + boundary + twoHyphens + end);

		fStream.close();
		ds.flush();

		//上传完成以后获取服务器的反馈
		InputStream is = con.getInputStream();
		int ch;
		StringBuffer b = new StringBuffer();
		while ((ch = is.read()) != -1) {
			b.append((char) ch);
		}

		ds.close();
		return b.toString();
	}

CustomFileInputStream.java

package com.huxq.uploadexample;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class CustomFileInputStream extends FileInputStream {
	private OnUploadListener listener;
	private int total, done;
	private double process;

	public CustomFileInputStream(File file) throws FileNotFoundException {
		super(file);
		available();
	}

	public CustomFileInputStream(FileDescriptor fd) {
		super(fd);
		available();
	}

	public CustomFileInputStream(String path) throws FileNotFoundException {
		super(path);
		available();
	}

	@Override
	public int read(byte[] buffer, int byteOffset, int byteCount)
			throws IOException {
		done += byteCount;
		process = 1.0 * done / total;
		if (listener != null) {
			listener.onUpload(process);
		}
		return super.read(buffer, byteOffset, byteCount);
	}

	public void setOnUploadListener(OnUploadListener listener) {
		this.listener = listener;
	}

	@Override
	public int available() {
		try {
			// 获取文件的总大小
			total = super.available();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return total;
	}
}

OnUploadListener.java

package com.huxq.uploadexample;

public interface OnUploadListener {
	void onUpload(double process);
}

服务器端:

服务器端通过一个servlet来接收文件流,然后写入磁盘就行了。

Upload.java

package com.huxq.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

/**
 * Servlet implementation class Upload
 */
@WebServlet("/Upload")
public class Upload extends HttpServlet {
	private static final long serialVersionUID = 1L;
	/**
	 * 文件保存路径
	 */
	private final String savaPath="E:\\uploads/";

	/**
	 * Default constructor.
	 */
	public Upload() {
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		if (isMultipart) {
			FileItemFactory factory = new DiskFileItemFactory();
			ServletFileUpload upload = new ServletFileUpload(factory);
			List items;
			try {
				items = upload.parseRequest(request);
				Iterator iter = items.iterator();
				// 可以接收多个文件
				while (iter.hasNext()) {
					FileItem item = (FileItem) iter.next();
					if (item.isFormField()) {
						// 普通文本信息处理
						String paramName = item.getFieldName();
						String paramValue = item.getString();
						System.out.println(paramName + ":" + paramValue);
					} else {
						// 上传文件信息处理
						String fileName = item.getName();
						byte[] data = item.get();
						String filePath = savaPath + fileName;
						File file = new File(savaPath);
						if (!file.exists()) {
							file.mkdirs();
						}
						System.out.println("filePath:" + filePath);
						File file2 = new File(filePath);
						if (file2.exists())
							file2.delete();
						FileOutputStream fos = new FileOutputStream(file2);
						fos.write(data);
						fos.close();
					}
				}
				response.getWriter().write("UPLOAD_SUCCESS");
			} catch (FileUploadException e) {
				e.printStackTrace();
				response.getWriter().write("UPLOAD_FAILED");
			}
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

这里需要两个jar包,分别是commons-fileupload-1.3.1.jar和commons-io-2.4.jar

所有想说的都在代码里了,如果有不清楚的可以下载下载Demo或者留言一起探讨。

时间: 2024-08-05 10:54:34

Android文件上传-本地+服务器一条龙分析的相关文章

Android文件上传至服务器

项目演示及讲解 优酷  http://v.youku.com/v_show/id_XODk5NjkwOTg4.html 爱奇艺  http://www.iqiyi.com/w_19rs1v2m15.html#vfrm=8-7-0-1 土豆  http://www.tudou.com/programs/view/fv0H93IHfhM 项目下载 1.手机端选择文件上传至服务器端 http://download.csdn.net/detail/u010134178/8457679 2.手机端拍照上传

C# winform把本地文件上传到服务器上,和从服务器上下载文件

昨天在做项目过程中遇到需要把本地文件上传到服务器上的问题,在这里记录一下,方便大家互相学习! /// <summary> /// 上传文件方法/// </summary> /// <param name="filePath">本地文件所在路径(包括文件)</param> /// <param name="serverPath">文件存储服务器路径(包括文件)</param> public voi

在Android浏览器中通过WebView调用相机拍照/选择文件 上传到服务器

最近做的一个项目中,有这样一个要求,在浏览器中调用系统的拍照功能或者选择文件,然后将文件上传到服务器,类似修改头像.        简单而言,就是在一个html页面中有这样一段代码 <input class="filePrew" type="file" capture="camera" accept="image/*" name="image"> 刚开始的时候,没有感觉很难的,因为在UC浏览器.

Hadoop之HDFS原理及文件上传下载源码分析(下)

上篇Hadoop之HDFS原理及文件上传下载源码分析(上)楼主主要介绍了hdfs原理及FileSystem的初始化源码解析, Client如何与NameNode建立RPC通信.本篇将继续介绍hdfs文件上传.下载源解析. 文件上传 先上文件上传的方法调用过程时序图: 其主要执行过程: FileSystem初始化,Client拿到NameNodeRpcServer代理对象,建立与NameNode的RPC通信(楼主上篇已经介绍过了) 调用FileSystem的create()方法,由于实现类为Dis

.net 文件上传到服务器【转】

最忌你在一个文档管理系统,包裹文件上传下载等. http://blog.csdn.net/pmy_c_l/article/details/73743843 官方链接:https://msdn.microsoft.com/zh-cn/library/system.io.filestream.read.aspx /// <summary> /// 读取本地文件上传到服务器 /// </summary> /// <param name="localfilepath&quo

c# 单个文件上传至服务器

#region 单个文件上传至服务器 /// <summary> /// 单个文件上传至服务器 /// </summary> /// <param name="uriAddress">接收文件资源的URI, 例如: http://xxxx/Upload.aspx?UID=11111</param> /// <param name="filePath">要发送的资源文件, 例如: @"D:\work

文件上传至服务器

使用文件上传至服务器需要导入两包commons-fileupload-1.2.2.jar与commons-io-2.4.jar 本文的servlet使用的是 servlet3.0注解配置,   不用写web.xml 文件了 建立文件时使用javaEE6.0 支持servlet3.0 value的值就是访问路径 urlPatterns的值也是访问路径  例如 @WebServlet(name="DemoServlet3",value="/demoServlet3")

客户端的文件上传到服务器,服务器返回文件的路径

客户端的文件上传到服务器,服务器返回文件的路径 返回信息,客户端将文件保存 客户端: <?php header('content-type:text/html;charset=utf8'); $url = 'http://192.168.1.118/legcc/aaa.php';//访问的服务器的地址 $curl = curl_init(); $path = 'D:\www\ceshi\a02.jpeg';//客户端文件的绝对路径 $source = file_get_contents($pat

Linux 文件上传Linux服务器

进入命令行 在图形化桌面出现之前,与Unix系统进行交互的唯一方式就是借助由shell所提供的文本命令行界面(command line interface,CLI).CLI只能接受文本输入,也只能显示出文本和基本的图形输出.众所周知,如今的Linux环境已经发生了巨大变化,所有的Linux发行版都配备了某种类型的图形化桌面环境.但是,如果向输入shell命令,仍然需要使用文本显示来访问shell的CLI. Linux发行版通常使用Ctrl+Alt组合键配合F1或F7来进入图形界面.Ubuntu使