Android中服務器端與客戶端交互

一:服務器端建立

1:下載Tomcat 以及 struts(框架:爲了解決文件上傳更簡潔),後面會提供兩個資源的下載鏈接。然後解壓下載好的Tomcat和struts

2:配置tomcat:打開Myeclipse,打開window->perferences查找tomcat,然後將地址映射到上面解壓的Tomcat包。不知道是不是我的電腦配置出現問題,導致我在perferences中沒有查找到tomcat屬性。所以我在創建WEB project中發現了配置Tomcat路徑的地方,可參考1-5圖片,完成tomcat配置。創建的WEB工程如6圖 


3:引入strust包:

3.1:找到解壓後的struts2-blank.war包,將這個包在進行解壓,找到WEB-INF文件夾,將WEB-INF裏lib包內的架包拷貝到工程對應lib目錄下。

3.2:將WEB-INF\classes下的struts.xml拷貝到工程的src目錄下,裏面的代碼參考7圖


3.3:打開WEB-INF 中webxml文件,將以下代碼

<filter>
    <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
     <url-pattern>/*</url-pattern>
  </filter-mapping>  拷貝到工程中web.xml文件

3.4:配置好之後,選擇run as ,將之前配置的Tomcat作爲service服務開啓。

4:新建一個包:com.imook.action,然後新建一個類UserAction,然後服務器端所有的代碼如下:

package com.imook.action;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Logger;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{
	
	
	private String username;
	private String password;
	
	public File mPhoto;
	public String mPhotoFileName;
	
	
	//上傳字符串到服務器
	public String postString() throws IOException{
		HttpServletRequest request = ServletActionContext.getRequest();
		ServletInputStream is = request.getInputStream();
		
		System.out.println("sessionId=" + request.getSession().getId());
		
		StringBuilder sb = new StringBuilder();
		int len = 0;
		byte[] buf = new byte[1024];
		
		while((len = is.read(buf)) != -1){
			sb.append(new String(buf,0,len));
		}
		System.out.println(sb.toString());
		
		return null;
	}
	
	//重命名圖片以及username及password
	public String uploadInfo() throws IOException{
		
		System.out.println(username+"  ," + password);
		
		if(mPhoto == null){
			System.out.println(mPhotoFileName+"  is null .");
		}
		
		String dir = ServletActionContext.getServletContext().getRealPath("/files");
		File file = new File(dir,mPhotoFileName);
		
		FileUtils.copyFile(mPhoto, file);
		
		return null;
	}
	
	//上傳圖片文件
	public String postFile() throws IOException{
		HttpServletRequest request = ServletActionContext.getRequest();
		ServletInputStream is = request.getInputStream();
		
		System.out.println("sessionId=" + request.getSession().getId());
		

		String dir = ServletActionContext.getServletContext().getRealPath("files");
		File file = new File(dir,"wwx.jpg");
		
        	FileOutputStream fos = new FileOutputStream(file);
        
		int len = 0;
		byte[] buf = new byte[1024];
		
		while((len = is.read(buf)) != -1){
			fos.write(buf, 0, len);
		}
		HttpServletResponse response = ServletActionContext.getResponse();
		PrintWriter writer = response.getWriter();
		writer.write(dir);
		writer.flush();
		System.out.println("dir:"+dir);
		fos.flush();
		fos.close();
	
		
		return null;
	}
	
	
	//登陸
	public String login() throws IOException{
		HttpServletRequest request = ServletActionContext.getRequest();
		
		//userService.login(username,password);
		System.out.println("sessionId=" + request.getSession().getId());
		System.out.println(username+" , "+password);
		
		HttpServletResponse response = ServletActionContext.getResponse();
		PrintWriter writer = response.getWriter();
		writer.write("Login success !");
		writer.flush();
		
		return null;
	}
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}

}

5:對應的struts代碼:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <constant name="struts.devMode" value="true" />

    <package name="default" namespace="/" extends="struts-default">
   
   <action name="login" class="com.imook.action.UserAction" method = "login">
   </action>
   
    <action name="postString" class="com.imook.action.UserAction" method = "postString">
   </action>
   
    <action name="postFile" class="com.imook.action.UserAction" method = "postFile">
   </action>
    <action name="uploadInfo" class="com.imook.action.UserAction" method = "uploadInfo">
   </action>
    </package>

    <!-- Add packages here -->

</struts>


二:客戶端

      客戶端就是創建一個Android 工程,具體的請參考代碼:

1:MainActivity代碼:

package nuro.nuro.okhttp;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.CookieManager;
import java.net.CookiePolicy;

public class MainActivity extends AppCompatActivity {
    private TextView tv_result;
    private ImageView iv_result;
    OkHttpClient okHttpClient = new OkHttpClient();
    private String mBaseUrl="http://192.168.1.113:8080/imook_okHttp/";
    private String TAG = "MainActivity";

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

        okHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ALL));//保證服務器端的sessionId保證一致,保證用戶登錄一致
        tv_result = (TextView) findViewById(R.id.tv_result);
        iv_result = (ImageView)findViewById(R.id.iv_result);

    }

    /*
    封裝代碼步驟
    * 1:拿到okHttpClient對象
    * 2:構造Request
      2.1構造requestBody
      2.2包裝requestBody
      3.call -> execute
    * */

    public void doPost(View view){
        //1:拿到okHttpClient對象
        FormEncodingBuilder requestBodyBuilder = new FormEncodingBuilder();
        //2:構造Request
        //2.1構造requestBody
        RequestBody requestBody = requestBodyBuilder.add("username","wwx").add("password","930820").build();
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(mBaseUrl + "login").post(requestBody).build();

        executeRequest(request);
    }

    public void doPostString(View view){
        //1:拿到okHttpClient對
        //2:構造Request
        //2.1構造requestBody
        RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain:charset=utf-8"), "{username:wwx,password:930820,sex:man,age:25}");
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(mBaseUrl + "postString").post(requestBody).build();

        executeRequest(request);
    }
    public void doPostFile(View view){
        File file = new File(Environment.getExternalStorageDirectory(),"wwx.jpg");
        Log.i(TAG,Environment.getExternalStorageState());
        if (!file.exists()){
            L.e(file.getAbsolutePath()+" not exist!");
            return;
        }
        //mime type查看各個文件的MediaType
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/octet-stream"),file);
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(mBaseUrl + "postFile").post(requestBody).build();

        executeRequest(request);
    }

    public void doUpload(View view){
        File file = new File(Environment.getExternalStorageDirectory(),"ziji.png");
        Log.i(TAG,Environment.getExternalStorageState());
        if (!file.exists()){
            L.e(file.getAbsolutePath()+" not exist!");
            return;
        }

        MultipartBuilder multipartBuilder = new MultipartBuilder();

        RequestBody requestBody = multipartBuilder.type(MultipartBuilder.FORM)//
                .addFormDataPart("username", "wwx")//
                .addFormDataPart("password", "930820")//
                .addFormDataPart("mPhoto", "jizi.png", RequestBody.create(MediaType.parse("application/octet-stream"), file))
                .build();

        CountingRequestbody countingRequestbody = new CountingRequestbody(requestBody, new CountingRequestbody.Listner() {
            @Override
            public void onRequestProgress(long bytesWrited, long contentLength) {
                L.e(bytesWrited + "/" + contentLength);
            }
        });


        //mime type查看各個文件的MediaType
        Request.Builder builder = new Request.Builder();
        Request request = builder.url(mBaseUrl + "uploadInfo").post(countingRequestbody).build();

        executeRequest(request);
    }

    public void doDownload(View view){
        Request.Builder builder = new Request.Builder();
        Request request = builder.get().url(mBaseUrl+"files/wwx.jpg").build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {//異步執行
            @Override
            public void onFailure(Request request, IOException e) {
                L.e("onFailure :" + e.getMessage());
                e.printStackTrace();
            }

            @Override
            public void onResponse(Response response) throws IOException {
                L.e("onResponse :");

                final long total = response.body().contentLength();//文件總長度
                long sum = 0L;
                InputStream is = response.body().byteStream();

                int len = 0;
                File file = new File(Environment.getExternalStorageDirectory(), "wwx12306.jpg");
                byte[] buf = new byte[128];
                FileOutputStream fos = new FileOutputStream(file);

                while ((len = is.read(buf)) != -1) {
                    fos.write(buf, 0, len);

                    sum += len;//進度比例

                    L.e(sum + "/" + total);
                    final long finalsum = sum;
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv_result.setText(finalsum+"/"+total);
                        }
                    });
                }
                fos.flush();
                fos.close();
                is.close();

                L.e("download success!");
            }
        });

    }

    public void doDownloadImg(View view){
        Request.Builder builder = new Request.Builder();
        Request request = builder.get().url(mBaseUrl+"files/jizi.png").build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {//異步執行
            @Override
            public void onFailure(Request request, IOException e) {
                L.e("onFailure :" + e.getMessage());
                e.printStackTrace();
            }

            @Override
            public void onResponse(Response response) throws IOException {
                L.e("onResponse :");
                InputStream is = response.body().byteStream();

                final Bitmap bitmap = BitmapFactory.decodeStream(is);

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        iv_result.setImageBitmap(bitmap);
                    }
                });

            }
        });

    }
    public void doGet(View view) throws IOException {
        //1:拿到okHttpClient對象

        //2:構造Request
        Request.Builder builder = new Request.Builder();
        Request request = builder.get().url(mBaseUrl+"login?username=wwx&password=654321").build();
        executeRequest(request);
    }

    private void executeRequest(Request request) {
        //3:將request封裝成call
        Call call = okHttpClient.newCall(request);

        //4:執行
        //call.execute();//立即執行
        call.enqueue(new Callback() {//異步執行
            @Override
            public void onFailure(Request request, IOException e) {
                L.e("onFailure :" + e.getMessage());
                e.printStackTrace();
            }

            @Override
            public void onResponse(Response response) throws IOException {
                L.e("onResponse :");
                final String res = response.body().string();
                L.e(res);//此時是子線程,不能直接設置UI控件更新的原因可能是爲了支持大文件的下載
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_result.setText(res);
                    }
                });
            }
        });
    }

}
     2:xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="nuro.nuro.okhttp.MainActivity"
    tools:showIn="@layout/activity_main">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get"
        android:onClick="doGet"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="post"
        android:onClick="doPost"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="post String"
        android:onClick="doPostString"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="post File"
        android:onClick="doPostFile"/>

    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Upload"
    android:onClick="doUpload"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Download"
        android:onClick="doDownload"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="DownloadImage"
        android:onClick="doDownloadImg"/>

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <ImageView
        android:id="@+id/iv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"/>
</LinearLayout>

3:封裝的一個打印信息L代碼:
package nuro.nuro.okhttp;

/**
 * Created by Administrator on 2017/8/1.
 */
public class L{
    private static boolean debug = true;
    private static String TAG = "imook_okhttp";

    public static void e(String msg){
        if (debug){
            android.util.Log.e(TAG,msg);
        }
    }
}

4:在MainFest中記得添加相應的權限:

     <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
    

三:總結:


這個例子介紹了服務器的簡單搭建,做到了Android客戶端上傳string(也可以是json格式),圖片、文件到服務器的指定目錄下,然後提供了從服務器上下載圖片文件的方法。


其中在:

1:客戶端上傳圖片到服務器中,因爲映射到服務器的地址不對,導致客戶端上傳的圖片,服務器一直沒有接收到。產生這個的原因是:沒有將Tomcat映射的路徑配置正確。正確的方式是要在新建web工程後配置Tomcat的路徑。

2:另外一個是比較大的圖片不能顯示,原因:代碼裏沒有增加壓縮圖片的步驟,部分圖片過大顯示不出來。

3:上傳以及下載的進度可以在進行完善,使用進度條來顯示。



各位:有不明白的或者有錯誤的地方,大家請指教。QQ:1143403680

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章