ブログ

Androidでサーバに画像をアップロードする方法

—————————
※2014年3月22日 追記
この方法だとAndroid4.0以上でエラーとなると思います。
エントリーの最後にAsyncTaskを使ったもっと簡単な方法を記載しています。
—————————

Androidアプリでサーバに画像をアップロードする方法。
まず、以下のjarファイルをダウンロードしてきて、プロジェクト内の「libs」フォルダに格納する。

apache-mime4j-core-0.7.2.jar(ダウンロードはこちら
httpclient-4.2.5.jar(ダウンロードはこちら
httpcore-4.2.4.jar(ダウンロードはこちら
httpcore-nio-4.2.4.jar(ダウンロードはこちら
httpmime-4.2.5.jar(ダウンロードはこちら

で、本来であれば、「カメラ」や「ギャラリーから選択」にintentして画像を取得する訳ですが、割愛。
SDカードの中のファイルを直接指定してサーバにアップロードしています。

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

		String sUrl = "http://hogehoge.com/uploads/";

		String fileName;
		String filePath;

		// 写真ディレクトリ用パス設定
		String strDirPath =
		Environment.getExternalStorageDirectory().getAbsolutePath()
		+ "/download/";

		// ディレクトリの作成
		makeDirectory(strDirPath);

		// ファイル名フォーマット取得
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");

		// ファイル作成、書き込み
		//fileName = dateFormat.format(today) + ".png";
		fileName = "001.png";

		filePath = strDirPath + fileName;
		int size = 2048;

		FileOutputStream stream = null;
		try {
			stream = new FileOutputStream(filePath);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		try {
			stream.write(size);
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			stream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// サーバへ画像を送信
		HttpClient client = new DefaultHttpClient();
		HttpPost httpPost = new HttpPost(sUrl);

		// Basic認証するUserとPasswordを設定
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials( "username", "password" );
        AuthScope scope = new AuthScope( httpPost.getURI().getHost(), httpPost.getURI().getPort() );
        ((AbstractHttpClient) client).getCredentialsProvider().setCredentials( scope, credentials );


		File upfile = new File( filePath );
		MultipartEntity mentity = new MultipartEntity();
		mentity.addPart("upfile", new FileBody(upfile));

		// レスポンス取得
		httpPost.setEntity(mentity);
		HttpResponse response = null;
		try {
			response = client.execute(httpPost);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// レスポンス取得
        HttpEntity entity = response.getEntity();
        String res = null;
        try {
			res = EntityUtils.toString( entity, "UTF-8" );
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
        // リソース解放
        try {
			entity.consumeContent();
		} catch (IOException e) {
			e.printStackTrace();
		}
        // 切断
        client.getConnectionManager().shutdown();

		TextView txtResult = (TextView) findViewById(R.id.txtResult);
		txtResult.setText(res.toString());






	}

	// ディレクトリの作成
	private boolean makeDirectory(String strDirPath) {
		boolean ret = false;
		File dir = new File(strDirPath);
		if (!dir.exists()) {
			ret = dir.mkdirs();
		} else {
			ret = true;
		}
		return ret;

	}

で、サーバ側では何をしているかというと、画像を受け取ってリネーム後、指定したディレクトリに移動。
そして300×300pxの正方形のサムネイルを生成しています。

< ?php
/* ========================================================================
 *
 * @category   Application of hoge
 * @author     woodsmall inc. <hoge@woodsmall.co.jp>
 * @copyright  2013 woodsmall inc.
 * @version    Rev 1.0.0
 * @link       http://woodsmall.co.jp
 *
 * @brie       画像のアップロードを行い、同時にサムネイルを生成する
 * @note
 *   
 * @param      N/A
 * @return     正常:アップロードファイル名   異常:エラーメッセージ
 * ========================================================================
*/


// パス設定
define("ROOT_PATH", realpath("../"));

$Y = ROOT_PATH. "/images/". date("Y");
$Ym = ROOT_PATH. "/images/". date("Y/m");
$Ymd = ROOT_PATH. "/images/". date("Y/m/d");
$rename_dir = $Ymd. "/". date("YmdHis"). ".png";
$thumb =  $Ymd. "/". date("YmdHis"). "-thumb.png";
$rename_file = date("YmdHis"). ".png";

if (is_uploaded_file($_FILES["upfile"]["tmp_name"])) { 
	if (move_uploaded_file($_FILES["upfile"]["tmp_name"], $_FILES["upfile"]["name"])) {
		chmod("files/" . $_FILES["upfile"]["name"], 0644);
		//echo $_FILES["upfile"]["name"] . "をアップロードしました。";
		
		// ディレクトリ作成
		mkdir( $Y, 0711 );
		mkdir( $Ym, 0711 );
		mkdir( $Ymd, 0711 );
		
		// 画像をリネームして移動
		rename($_FILES["upfile"]["name"], $rename_dir);
		
		// サムネイルを生成
		$file = $_FILES["upfile"]["name"];
		$image = imagecreatefrompng( $file );
		if ($image) {
		
			$width  = imagesx( $image );
			$height = imagesy( $image );
			if ( $width >= $height ) {
				//横長の画像の時
				$side = $height;
				$x = floor( ( $width - $height ) / 2 );
				$y = 0;
				$width = $side;
			} else {
				//縦長の画像の時
				$side = $width;
				$y = floor( ( $height - $width ) / 2 );
				$x = 0;
				$height = $side;
			}
			
			
			$thumbnail_width  = 300;
			$thumbnail_height = 300;
			$thumbnail = imagecreatetruecolor( $thumbnail_width, $thumbnail_height );
			
			
//			imagecopyresized( $thumbnail, $image, 0, 0, $x, $y, $thumbnail_width, $thumbnail_height, $width, $height );
			imagecopyresampled( $thumbnail, $image, 0, 0, $x, $y, $thumbnail_width, $thumbnail_height, $width, $height );
			$result = imagepng( $thumbnail, $thumb );
			if ($result) {
				echo $rename_dir;
			} else {
				echo "ERROR imagepng!!n". $Ymd;
			}
		} else {
			echo "ERROR imagecreatefrompng!!n";
		}
		
		// メモリ上の画像データを破棄
		imagedestroy($image);
		imagedestroy($thumbnail);

	} else {
		echo "ファイルをアップロードできません。";
	}
} else {
	echo "ファイルが選択されていません。";
}

できれば、AndroidとiPhoneで共通したサーバ側のAPIを使用したいところなんだけど、iPhoneで画像をアップする方法は若干違うっぽい。
なので、APIもiPhone用を開発しなきゃっぽい。

iPhoneの画像アップロード方法は、また後ほど。

—————————
※2014年3月22日 追記

AsyncTaskを使ったソース(Android側)もスッキリする書き方です。

1.jarをダウンロードし、プロジェクトのlibsフォルダに配置

httpcore-4.3.4.jar(ダウンロードはこちら
httpmime-4.3.3.jar(ダウンロードはこちら
※こちらはアップデートされているので、最新版をダウンロード

2.AsyncTaskを継承したクラスを作成

import java.io.File;
import java.io.IOException;

import jp.co.tokyobay.btnet.R;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.widget.Toast;

@SuppressWarnings("deprecation")
public class UploadAsyncTask extends AsyncTask<String , Integer, Integer> {

	public Context context;
	private String ReceiveStr;
	public int iCnt;

	public UploadAsyncTask(Context context) {
		this.context = context;
	}

	@SuppressWarnings("deprecation")
	@Override
	protected Integer doInBackground(String... params) {
		try {
			String fileName = params[0];


			// URLパラメータを取得
			String sId= "";
			/* 処理 */

			// パラメータ作成
			String sPar = "";
			if (mCommon.isNullOrEmpty(sId)) {
				sPar = "?" + Constants._ID + "=";
			} else {
				sPar = "?" + Constants._ID + "=" + sId;
			}


			HttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(Constants.SERVER_URL + Constants.API_UPLOAD_AUDIO + sPar);
			ResponseHandler</string><string> responseHandler =
					new BasicResponseHandler();

			MultipartEntity multipartEntity = new MultipartEntity();

			File file = new File(fileName);
			FileBody fileBody = new FileBody(file);
			multipartEntity.addPart("upfile", fileBody);

			httpPost.setEntity(multipartEntity);

			ReceiveStr = httpClient.execute(httpPost, responseHandler);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return 0;
	}

	@Override
	protected void onPostExecute(Integer result) {
		// サーバ側phpでechoした内容を表示
		Toast.makeText(context, ReceiveStr, Toast.LENGTH_LONG)
		.show();

	}

}

mCommonってのは、共通クラスです。
Constantsってのは、共通の定数を定義したクラスです。
Constants.SERVER_URL + Constants.API_UPLOAD_AUDIOにサーバ側のURLが入っています。
サーバ側で処理分岐させるため、URLパラメータを付与しています。
サーバ側のphpが呼ばれるとonPostExecute()メソッドが呼ばれます。
ここでサーバ側で出力した内容によって処理分岐とか出来ます。

3.呼び出し側のActivity

	// サーバにアップロード
	UploadAsyncTask task = new UploadAsyncTask(
			me);
	task.context = me;
	task.iCnt = iCount;
	task.execute(filePath);

“me”はローカル変数で、(アクティビティ名).thisというContextが入っています。
filePathにローカルファイルのパスが入っています。

これでやれば、サーバとのやりとりも非同期でやってくれるし、ソースもスッキリ。
jarファイルも2つでできます。

良かったら参考にしてみてください。
—————————

スポンサードリンク

  • このエントリーをはてなブックマークに追加

関連記事

スポンサードリンク

 

30代半ばのオッサンが起業した話

プロフィール

kobayashi-profile
代表取締役CEO 小林 高志
1999年からシステムエンジニアとして、クライアントサーバのシステム構築、WEBシステムの開発、Androidアプリの企画・開発、iPhoneアプリの企画・マーケティング等に携わる。
2012年からカメラマンとして都内のスタジオに従事。
2012年、株式会社woodsmall創業。
2013年5月に代表取締役に就任。
自身の半生を綴った書籍を出版するのが、個人的な目標。
趣味は、カメラ・車・バイク・料理。

代表取締役の略歴はこちら

社長のブログについて

検索してもヒットしなかったアプリ開発に関する技術的な記事から、その時に思ったことなどを素直に書き綴っています。

スポンサードリンク

Facebook

twitter

対応エリア

株式会社woodsmallは、千葉県をはじめ関東エリア、関西エリアでのホームページ制作、アプリ開発(Android、iPhone)、システム開発、チラシ制作を承ります。

【千葉県エリア】
船橋市、市川市、習志野市、浦安市、鎌ヶ谷市、松戸市、柏市、成田市、佐倉市、千葉市中央区、千葉市花見川区、千葉市稲毛区、千葉市美浜区、千葉市若葉区、千葉市緑区、白石市などの千葉県エリア

【東京都エリア】
足立区、荒川区、板橋区、江戸川区、大田区、葛飾区、北区、江東区、品川区、渋谷区、新宿区、杉並区、墨田区、世田谷区、台東区、中央区、千代田区、豊島区、中野区、練馬区、文京区、港区、目黒区などの東京都エリア

【神奈川県エリア】
横浜市、川崎市、藤沢市、茅ヶ崎市、大和市、海老名市、座間市、綾瀬市、平塚市、寒川町、大磯町、二宮町などの神奈川県エリア

【埼玉県エリア】
さいたま市、川口市、蕨市、戸田市などの埼玉県エリア

【関東・関西エリア】
その他、茨城県、栃木県、群馬県の関東エリア、長野県、新潟県の甲信越エリア、大阪府の関西エリア、全国からのご依頼に対応させて頂きます。
(遠方の場合は電話やメール、LINE、Skypeでの打合せとなります。)

ページ上部へ戻る