[android] 转上传图片到LAMP服务器

最近在弄一个项目,需要用到android拍照图片上传到LAMP服务器中去,网上找了很多代码,都不能实现上传文件,原因是当时使用的租用虚拟主机空间,文章是这么说的:

写道
通过前一篇转载的博文,已经可以实现上传图片、文件等。不过当时是在本地服务器,当我将PHP代码放到租用的虚拟主机的时候,就出现问题了。我POST请求在服务器那边获取不到任何数据。也就是说 $_POST 和 &_FILES 都是空的。而测试POST到本地的服务器,又很正常。这就很奇怪了。
为了确实是什么问题,我是这么做的:
我写了一个HTML的form表单,提交到远程服务器上,没问题。
然后用Fiddler抓包软件,抓取HTML的表单请求包和Android发送的请求包,对比。看看有什么不一样。
最后发现,在请求包里有Transfer-Encoding: chunked的时候,服务器就获取不到参数。
当没有Transfer-Encoding: chunked而有Content-Length: xxx的时候就没问题然后回头看看Android的代码,将
//这句注释掉。并记录整个请求包的大小,设置一下
//httpURLConnection.setChunkedStreamingMode(128 * 1024);
httpURLConnection.setRequestProperty("Content-Length", ""+Data.length);就好了。
不知道为什么租用的虚拟主机不支持,害得我调试了好久。还有之前的RSA生成、长链接的实现,都受虚拟主机限制的影响。
Transfer-Encoding: chunked 表示使用分块传输编码这一机制,只在 HTTP1.1里才有。
可以不事先确定整个Request包的大小,而是将数据分块发送。
在Body中就是 一个十六进制的数字表示接下来的包的长度,然后包的内容
Request的结束就是当分块包的长度为0。比如:
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
(转发请注明转自:学PHP)

 

贴上代码:

package com.uploaddemo.control;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.http.HttpStatus;
import org.apache.http.ProtocolException;

import android.content.Context;
import android.util.Log;

public class UploadHelper  {
	private static final String TAG = "salesman";

	private Context context = null;
	private String serverUrl = null;
	private String param1 = null;
	private String param2 = null;
	private String filePath = null;
	private String fileName = null;

	private static final int DEFAULT_BUFF_SIZE = 8192;
	private static final int READ_TIMEOUT = 15000;
	private static final int CONNECTION_TIMEOUT = 15000;

	private UploadListener uploadListener = null;

	public UploadHelper(Context context, String url, String param1, String param2, String filePath, String fileName) {
		this.context = context;
		this.serverUrl = url;
		this.param1 = param1;
		this.param2 = param2;
		this.filePath = filePath;
		this.fileName = fileName;
	}

	public void setUploadListener(UploadListener listener) {
		this.uploadListener = listener;
	}

	public void uploadFile() throws MalformedURLException, ProtocolException, FileNotFoundException, IOException {
		String lineEnd = "\r\n";
		String twoHyphens = "--";
		String boundary = "--------------et567z";// 各个参数的间隔符,可自定义,但不能与发送内容有重复部分

		if (context == null || serverUrl == null || param1 == null || param2 == null || filePath == null || fileName == null) {
			return;
		}

		URL url = new URL(serverUrl);
		HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
		// 设置每次传输的流大小,可以有效防止手机因为内存不足崩溃
		// 此方法用于在预先不知道内容长度时启用没有进行内部缓冲的 HTTP 请求正文的流。
		// 租用的服务器空间这里必须去掉否则服务器接收不了任何参数
		//httpURLConnection.setChunkedStreamingMode(128 * 1024);// 128K
		//httpURLConnection.setRequestProperty("Content-Length", ""+ 1024 * 1024);
		// 允许输入输出流
		httpURLConnection.setDoInput(true);
		httpURLConnection.setDoOutput(true);
		httpURLConnection.setUseCaches(false);
		// 超时时间设置
		httpURLConnection.setReadTimeout(READ_TIMEOUT);
		httpURLConnection.setConnectTimeout(CONNECTION_TIMEOUT);
		// 使用POST方法
		httpURLConnection.setRequestMethod("POST");
		httpURLConnection.setRequestProperty("Connection", "Keep-alive");
		httpURLConnection.setRequestProperty("Charset", "UTF-8");
		httpURLConnection.setRequestProperty("Content-Type", "Multipart/form-data;boundary=" + boundary);

		DataOutputStream dos = new DataOutputStream(httpURLConnection.getOutputStream());
		// 发送jsonStr
		dos.writeBytes(twoHyphens + boundary + lineEnd);
		dos.writeBytes("Content-Disposition: form-data; name=\"param1\"" + lineEnd);
		dos.writeBytes(lineEnd);
		dos.writeBytes(param1);
		dos.writeBytes(lineEnd);
		// 发送acrion
		dos.writeBytes(twoHyphens + boundary + lineEnd);
		dos.writeBytes("Content-Disposition: form-data; name=\"param2\"" + lineEnd);
		dos.writeBytes(lineEnd);
		dos.writeBytes(param2);
		dos.writeBytes(lineEnd);
		// 发送文件
		dos.writeBytes(twoHyphens + boundary + lineEnd);
		dos.writeBytes("Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"" + fileName + "\"" + lineEnd);
		dos.writeBytes(lineEnd);
		//dos.writeBytes("Content-Type: image/*\r\n\r\n");
		String srcPath = filePath + fileName;

		FileInputStream fis = new FileInputStream(srcPath);
		byte[] buffer = new byte[DEFAULT_BUFF_SIZE]; // 8k
		int counter = 0;
		int count = 0;
		// 读取文件
		while ((count = fis.read(buffer)) != -1) {
			dos.write(buffer, 0, count);
			counter += count;
			if (uploadListener != null) {
				uploadListener.onUploadProcess(counter);
			}
		}
		fis.close();

		dos.writeBytes(lineEnd);
		dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);// 最后多出"--"作为结束
		dos.flush();

		if (httpURLConnection.getResponseCode() == HttpStatus.SC_OK) {
			BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()), 8192);// 8k
			StringBuilder sb = new StringBuilder();
			String line = null;
			try {
				while ((line = reader.readLine()) != null) {
					sb.append(line + "\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (uploadListener != null) {
				uploadListener.onUploadFinished(sb.toString());
			}
			Log.e("salesman", "show.........");
		} else {
			Log.e(TAG, "Http request failed!");
			if (uploadListener != null) {
				uploadListener.onUploadFinished("Http request failed!");
			}
		}

		if (httpURLConnection != null) {
			httpURLConnection.disconnect();
		}
	}
}

 

package com.uploaddemo.control;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ProtocolException;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class UploadDemoActivity extends Activity {
    private TextView txtVServerUrl = null;
	private TextView txtVFilePath = null;
	private Button btnUpload = null;
	private ProgressBar progressBar = null;

	private String filePath = Environment.getExternalStorageDirectory() + "/salesman/";
	private String fileName = "test.jpg";
	private String serverUrl = "http://www.bocn.com/upload.php";

	private Handler handler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			if (msg.what == 0) {
				progressBar.setProgress(msg.arg1);
			} else if (msg.what == 1) {
				Bundle b = msg.getData();
				if (b == null) {
					return;
				}
				String str = b.getString("msg");
				Toast.makeText(UploadDemoActivity.this, str, Toast.LENGTH_LONG).show();
			}
		}

	};

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		txtVServerUrl = (TextView) findViewById(R.id.ID_TxtV_ServerUrl);
		txtVServerUrl.setText("serverUrl:" + serverUrl);
		txtVFilePath = (TextView) findViewById(R.id.ID_TxtV_FilePath);
		txtVFilePath.setText("filePath:" + filePath + fileName);

		progressBar = (ProgressBar) findViewById(R.id.ID_PBar);
		File file = new File(filePath, fileName);

		progressBar.setMax((int) file.length());

		btnUpload = (Button) findViewById(R.id.ID_Btn_Upload);
		btnUpload.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				final UploadHelper UploadHelper = new UploadHelper(UploadDemoActivity.this, serverUrl, "heihei", "haha", filePath, fileName);
				UploadHelper.setUploadListener(new UploadListener() {

					@Override
					public void onUploadProcess(int size) {
						Message msg = new Message();
						msg.what = 0;
						msg.arg1 = size;
						handler.sendMessage(msg);
					}

					@Override
					public void onUploadFinished(String msg) {
						Message msg1 = new Message();
						msg1.what = 1;
						Bundle b = new Bundle();
						b.putString("msg", msg);
						msg1.setData(b);
						handler.sendMessage(msg1);
					}
				});

				new Thread() {
					@Override
					public void run() {
						try {
							UploadHelper.uploadFile();
						} catch (MalformedURLException e) {
							e.printStackTrace();
						} catch (ProtocolException e) {
							e.printStackTrace();
						} catch (FileNotFoundException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						} catch (org.apache.http.ProtocolException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}

				}.start();

			}
		});
	}
}

 

package com.uploaddemo.control;

public interface UploadListener {

	public void onUploadProcess(int size);

	public void onUploadFinished(String msg);
}

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
	<TextView  
		android:id="@+id/ID_TxtV_FilePath"
	    android:layout_width="fill_parent" 
	    android:layout_height="wrap_content" 
	    android:text="@string/hello"
	    />
	<TextView 
	android:text="TextView" android:id="@+id/ID_TxtV_ServerUrl" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
	<ProgressBar android:id="@+id/ID_PBar" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal" android:layout_width="259dp"></ProgressBar>
	<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/ID_Btn_Upload" android:text="上传"></Button>
</LinearLayout>

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.uploaddemo.control"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="9" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".UploadDemoActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    
    <uses-permission android:name="android.permission.VIBRATE" />
	<uses-permission android:name="android.permission.INTERNET" />
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.RESTART_PACKAGES" />
	<uses-permission android:name="android.permission.READ_PHONE_STATE" />
	<uses-permission android:name="android.permission.READ_LOGS" />
	<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>

 

<?php  
echo "param1=".$_POST['param1'].chr(13).chr(10);
echo "param2=".$_POST['param2'].chr(13).chr(10);
$target_path  = "./upload/";//接收文件目录  
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);  
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {  
   echo "The file ".  basename( $_FILES['uploadedfile']['name']). " has been uploaded";  
}  else{  
   echo "There was an error uploading the file, please try again!" . $_FILES['uploadedfile']['error'];  
}  
?> 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值