Android开发笔记(一百一十)使用http框架上传文件

这篇博客详细介绍了在Android开发中如何进行文件上传,包括使用HttpURLConnection、android-async-http和Retrofit框架的实现步骤,并探讨了服务器端通过commons-fileupload接收文件以及普通FTP和安全SFTP的上传方法。
摘要由CSDN通过智能技术生成

HTTP上传

与文件下载相比,文件上传的场合不是很多,通常用于上传用户头像、朋友圈发布图片/视频动态等等,而且上传文件需要服务器配合,所以容易被app开发者忽略。就上传的形式来说,app一般采用http上传文件,很少用ftp上传文件。


HttpURLConnection上传

很可惜Android没有提供专门的文件上传工具类,所以我们要自己写代码实现上传功能了。其实也不难,一样是按照普通网络访问的POST流程,只是要采用“multipart/form-data”方式来分段传输。另外文件上传需要运用打开文件的对话框,文件对话框的介绍参见《 Android开发笔记(二十三)文件对话框FileDialog》。


下面是HttpURLConnection上传文件的工具类代码:
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class UploadUtil {
	private static final String TAG = "UploadUtil";
	
	public static String upload(String uploadUrl, String uploadFile) {
		String fileName = "";
		int pos = uploadFile.lastIndexOf("/");
		if (pos >= 0) {
			fileName = uploadFile.substring(pos + 1);
		}
		
		String end = "\r\n";
		String Hyphens = "--";
		String boundary = "WUm4580jbtwfJhNp7zi1djFEO3wNNm";
		try {
			URL url = new URL(uploadUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Charset", "UTF-8");
			conn.setRequestProperty("Content-Type",
					"multipart/form-data;boundary=" + boundary);

			DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
			ds.writeBytes(Hyphens + boundary + end);
			ds.writeBytes("Content-Disposition: form-data; "
					+ "name=\"file1\";filename=\"" + fileName + "\"" + end);
			ds.writeBytes(end);
			FileInputStream fStream = new FileInputStream(uploadFile);
			// 每次写入1024字节
			int bufferSize = 1024;
			byte[] buffer = new byte[bufferSize];
			int length = -1;
			// 将文件数据写入到缓冲区
			while((length = fStream.read(buffer)) != -1) { 
				ds.write(buffer, 0, length);
			}
			ds.writeBytes(end);
			ds.writeBytes(Hyphens + boundary + Hyphens + end);
			fStream.close();
			ds.flush();
			// 获取返回内容
			InputStream is = conn.getInputStream();
			int ch;
			StringBuffer b = new StringBuffer();
			while ((ch = is.read()) != -1) {
				b.append((char) ch);
			}
			ds.close();
			return "SUCC";
		} catch (Exception e) {
			e.printStackTrace();
			return "上传失败:" + e.getMessage();
		}
	}
}


android-async-http上传

HttpURLConnection需要开发者自己拼接请求包,容易出错,并且处理单一不够灵活,因此涌现了几个开源的http框架,方便开发者进行http通信的编码。android-async-http是这其中使用较多的一个网络请求框架,它的项目地址在 https://github.com/loopj/android-async-http 。


据官方介绍,android-async-http是基于Apache HttpClient库之上的一个异步网络请求处理库,网络处理均基于Android的非UI线程,通过回调方法处理请求结果。这里我们使用该库进行文件上传,主要用到AsyncHttpClient类的post方法,要上传的文件信息放在RequestParams对象中。


下面是android-async-http上传文件的工具类代码:
import java.io.File;

import com.example.exmupload.MainActivity;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.RequestParams;

import android.util.Log;

public class AsyncUtil {
    private static final String TAG = "AsyncUtil";
	
	public static String upload(final MainActivity act, String uploadServlet, String filePath, boolean isBinary) {
		try {
			//服务端的commons-fileupload只支持multipart/form-data方式
			//application/octet-stream表示任意的二进制文件,包括图片、音频、视频、压缩文件等等
			String contentType = "application/octet-stream";
			//String contentType = "multipart/form-data";
			RequestParams params = new RequestParams();
			if (isBinary == true) {
				params.put("file", new File(filePath), contentType);
			} else {
				params.put("file", new File(filePath));
			}
			Log.d(TAG, "contentType="+contentType);
			AsyncHttpClient client = new AsyncHttpClient();
			//AsyncHttpResponseHandle不在ui线程运行,不能直接操作ui
			//如果在此处定义AsyncHttpResponseHandle对象,则运行报错:
			//java.lang.IllegalArgumentException: Synchronous ResponseHandler used in AsyncHttpClient. You should create your response handler in a looper thread or use SyncHttpClient instead.
			client.post(uploadServlet, params, act.mAsyncHandler);
			return "uploadByFile";
		} catch (Exception e) {
			e.printStackTrace();
			return e.getMessage();
		}
	}

//	//下面代码在MainActivity.java中定义
//	public AsyncHttpResponseHandler mAsyncHandler = new AsyncHttpResponseHandler() {
//		@Override
//		public void onSuccess(int status, Header[] headers, byte[] data) {
//			String result = "文件上传成功!";
//			Message msg = Message.obtain();
//			msg.what = ASYNC;
//			msg.obj = result;
//			mHandle
package com.loopj.android.image; import android.content.Context; import android.graphics.Bitmap; import android.util.AttributeSet; import android.widget.ImageView; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class SmartImageView extends ImageView { private static final int LOADING_THREADS = 4; private static ExecutorService threadPool = Executors.newFixedThreadPool(LOADING_THREADS); private SmartImageTask currentTask; public SmartImageView(Context context) { super(context); } public SmartImageView(Context context, AttributeSet attrs) { super(context, attrs); } public SmartImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } // Helpers to set image by URL public void setImageUrl(String url) { setImage(new WebImage(url)); } public void setImageUrl(String url, SmartImageTask.OnCompleteListener completeListener) { setImage(new WebImage(url), completeListener); } public void setImageUrl(String url, final Integer fallbackResource) { setImage(new WebImage(url), fallbackResource); } public void setImageUrl(String url, final Integer fallbackResource, SmartImageTask.OnCompleteListener completeListener) { setImage(new WebImage(url), fallbackResource, completeListener); } public void setImageUrl(String url, final Integer fallbackResource, final Integer loadingResource) { setImage(new WebImage(url), fallbackResource, loadingResource); } public void setImageUrl(String url, final Integer fallbackResource, final Integer loadingResource, SmartImageTask.OnCompleteListener completeListener) { setImage(new WebImage(url), fallbackResource, loadingResource, completeListener); } // Helpers to set image by contact address book id public void setImageContact(long contactId) { setImage(new ContactImage(contactId)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值