使用.NET框架、Web service实现Android的文件上传(二)

本文是在《使用.NET框架、Web service实现Android的文件上传(一)》的基础上继续编写的,如有疑问请先查看第一篇。本文的代码(包括客户端与服务端)已经上传至GitHub,地址:https://github.com/weifengzz/UploadFile_1

  要想实现大文件上传,如果使用第一篇讲到的方法是很不合适的,因为手机内存是有限的,而我们上传的文件的大小是不确定的。如果文件比较大的话,我在夜神模拟器上的测试结果是,文件在10M以内就会出现内存溢出的情况。那么要想实现大文件的上传,我们就需要将文件以规定的某一大小进行分割(文中是以100K的大小进行分割的),然后进行上传,最后在服务端将文件进行合并,这样就实现了文件的上传。下面开始介绍一下实现大文件上传的主要代码:

一、文件读取工具类

 1 import java.io.IOException;
 2 import java.io.RandomAccessFile;
 3 import java.io.Serializable;
 4 
 5 /**
 6  * Created by WFZ on 2015/12/8.
 7  */
 8 public class BigRandomAccessFile implements Serializable {
 9 
10     RandomAccessFile randomAccessFile = null;
11     long nPos;//从文件的;哪一个地方开始读
12 
13     public BigRandomAccessFile(String fName, long nPos) throws IOException {
14         randomAccessFile = new RandomAccessFile(fName, "rw");//创建一个随机访问文件类,可读写模式
15         this.nPos = nPos;
16         randomAccessFile.seek(nPos);
17     }
18 
19     /**
20      * 写文件,
21      * 写b数组长的文件,
22      * 从哪个地方开始写,
23      * 写的长度
24      * 返回写的长度
25      */
26     public synchronized int write(byte[] b, int nStart, int nLen) {
27         int n = -1;
28         try {
29             randomAccessFile.write(b, nStart, nLen);
30             n = nLen;
31         } catch (IOException e) {
32             e.printStackTrace();
33         }
34         return n;
35     }
36 
37     /**
38      * 读取文件
39      * @param length 每次读取字节数
40      */
41     public synchronized Detail getContent(long nStart,int length) {
42         Detail detail = new Detail();
43         detail.b = new byte[length];
44         try {
45             randomAccessFile.seek(nStart);
46             detail.length = randomAccessFile.read(detail.b);//读了多长的数据
47         } catch (IOException e) {
48             e.printStackTrace();
49         }
50         return detail;
51     }
52 
53     /**
54      * 读取文件的信息
55      */
56     public class Detail {
57         public byte[] b;//读取文件的存放数据的byte数组
58         public int length;//读取的文件的长度
59     }
60 
61     /**
62      * 获取文件长度
63      */
64     public long getFileLength() {
65         Long length = 0L;
66         try {
67             length = randomAccessFile.length();
68         } catch (IOException e) {
69             // TODO Auto-generated catch block
70             e.printStackTrace();
71         }
72         return length;
73     }
74 }

二、得到经过处理的Base64字符串

 1 import android.util.Base64;
 2 import com.lhgj.wfz.uploadfiles.utils.Fileutil;
 3 import java.io.File;
 4 
 5 /**
 6  *得到经过处理的Base64字符串
 7  */
 8 public class BigBase64Util {
 9     public static String getBase64String( byte[] byteArray) {
10         String strBase64 = new String(Base64.encode(byteArray,0));
11         return strBase64;
12     }
13 }

三、Activity类

  1 import android.app.ProgressDialog;
  2 import android.graphics.Bitmap;
  3 import android.graphics.BitmapFactory;
  4 import android.os.Handler;
  5 import android.os.Message;
  6 import android.support.v7.app.AppCompatActivity;
  7 import android.os.Bundle;
  8 import android.view.View;
  9 import android.widget.Button;
 10 import android.widget.ImageView;
 11 import android.widget.TextView;
 12 
 13 import com.lhgj.wfz.uploadfiles.BigUtils.BigBase64Util;
 14 import com.lhgj.wfz.uploadfiles.BigUtils.BigRandomAccessFile;
 15 import com.lhgj.wfz.uploadfiles.utils.Base64Util;
 16 import com.lhgj.wfz.uploadfiles.utils.Fileutil;
 17 import com.lhgj.wfz.uploadfiles.utils.QueryUploadUtil;
 18 
 19 import java.io.File;
 20 import java.io.IOException;
 21 
 22 public class MainActivity extends AppCompatActivity {
 23     private TextView tv1 = null;//上传的文件地址
 24     private TextView tv2 = null;//上传的文件名称
 25     private TextView tv3 = null;//上传是否成功提示
 26     private Button btn = null;//上传小图片按钮
 27     private ImageView img = null;//图片
 28     private Button bigBtn = null;//上传大图片的按钮
 29     private int i = 0;//记录上传的次数
 30     private ProgressDialog progressDialog = null;//进度条
 31 
 32     private String filePath = "/data/data/com.lhgj.wfz.uploadfiles/";//手机中文件存储的位置
 33     private String fileName = "temp.jpg";//上传的图片
 34     private String bigFileName = "lyf.mp4";//上传的图片
 35     private String wsdl = "http://192.168.15.4:1122/service/vedios/GetVedios.asmx?WSDL";//WSDL
 36     private String url = "http://192.168.15.4:1122/service/vedios/GetVedios.asmx/FileUploadByBase64String";//上传小文件与webservice交互的地址
 37     private String bigUrl = "http://192.168.15.4:1122/service/vedios/GetVedios.asmx/BigFileUploadByBase64String";//上传大文件与webservice交互的地址
 38 
 39     /**
 40      * 由于上传文件是一个耗时操作,需要开一个异步,这里我们使用handle
 41      */
 42     private Handler handler = new Handler() {
 43         public void handleMessage(android.os.Message msg) {
 44             String string = (String) msg.obj;
 45             tv3.setText(string +"本文件上传次数:"+ i++);
 46         }
 47     };
 48 
 49     @Override
 50     protected void onCreate(Bundle savedInstanceState) {
 51         super.onCreate(savedInstanceState);
 52         setContentView(R.layout.activity_main);
 53         initView();
 54     }
 55 
 56         /**
 57          * 初始化view
 58          */
 59     private void initView() {
 60         tv1 = (TextView) findViewById(R.id.tv1);
 61         tv2 = (TextView) findViewById(R.id.tv2);
 62         tv3 = (TextView) findViewById(R.id.tv3);
 63         btn = (Button) findViewById(R.id.btn);
 64         img = (ImageView) findViewById(R.id.iv);
 65         bigBtn = (Button) findViewById(R.id.big_btn);
 66 
 67         //设置显示的图片
 68         byte[] byteArray = null;
 69         byteArray = Fileutil.readFileToByteArray(new File(filePath + fileName));
 70         Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0,
 71                 byteArray.length);
 72         img.setImageBitmap(bitmap);
 73 
 74         //设置显示的文本
 75         tv1.setText("文件位置:" + filePath);
 76         tv2.setText("文件名称" + fileName);
 77 
 78         //进度条
 79         progressDialog = new ProgressDialog(MainActivity.this);
 80         btn.setOnClickListener(new BtnOnclickListener());
 81         bigBtn.setOnClickListener(new BtnOnclickListener());
 82         //设置标题
 83         progressDialog.setTitle("文件上传");
 84         //设置最大进度
 85         progressDialog.setMax(100);
 86         //设置显示的信息
 87         progressDialog.setMessage("文件正上传...");
 88         //设置是否可以点击
 89         progressDialog.setCancelable(false);
 90         //设置ProgressBar的样式
 91         progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
 92     }
 93 
 94     /**
 95      * ImageView的事件响应
 96      */
 97     private class BtnOnclickListener implements View.OnClickListener {
 98 
 99         @Override
100         public void onClick(View v) {
101             switch (v.getId()) {
102                 case R.id.btn://当是上传小文件的时候
103                     upSmallFile();
104                     break;
105                 case R.id.big_btn://当上传大文件的时候
106                     upBigFile();
107                     break;
108             }
109 
110         }
111     }
112 
113     /**
114      * 上传小文件
115      */
116     public void upSmallFile() {
117         new Thread(new Runnable() {
118 
119             @Override
120             public void run() {
121                 // TODO Auto-generated method stub
122                 Message message = Message.obtain();
123                 String result = "";
124                 try {
125                     QueryUploadUtil quu = new QueryUploadUtil(Base64Util.getBase64String(filePath + fileName), "temp.jpg");
126                     result = quu.call(wsdl, url,"FileUploadByBase64String");
127                 } catch (Exception e) {
128                     // TODO Auto-generated catch block
129                     e.printStackTrace();
130                 }
131                 message.obj = result;
132                 handler.sendMessage(message);
133             }
134         }).start();
135     }
136 
137     /**
138      * 上传大文件
139      */
140     public void upBigFile() {
141         progressDialog.show();//显示进度条
142         new Thread(new Runnable() {
143             @Override
144             public void run() {
145                 try {
146 
147                     BigRandomAccessFile bigRandomAccessFile = new BigRandomAccessFile(filePath + bigFileName, 0);
148                     long startPos = 0L;
149                     Long length = bigRandomAccessFile.getFileLength();//得到文件的长度
150                     int mBufferSize = 1024 * 100; //每次处理1024 * 100字节
151                     byte[] buffer = new byte[mBufferSize];//创建一个mBufferSize大小的缓存数组
152                     BigRandomAccessFile.Detail detail;//文件的详情类
153                     long nRead = 0l;//读取文件的当前长度
154                     String vedioFileName = fileName; //分配一个文件名
155                     long nStart = startPos;//开始读的位置
156                     while (nStart < length) {//当开始都的位置比长度小的时候
157                         progressDialog.setProgress((int) ((nStart/(float)length)*100));//设置progressDialog的进度
158 
159                         detail = bigRandomAccessFile.getContent(startPos,mBufferSize);//开始读取文件
160                         nRead = detail.length;//读取的文件的长度
161                         buffer = detail.b;//读取文件的缓存
162                         Message message = Message.obtain();
163                         String result = "";//上传的结果
164                         try {
165                             QueryUploadUtil quu = new QueryUploadUtil(BigBase64Util.getBase64String(buffer), bigFileName);//将数据进行上传
166                             result = quu.call(wsdl, bigUrl,"BigFileUploadByBase64String");
167                         } catch (Exception e) {
168                             // TODO Auto-generated catch block
169                             e.printStackTrace();
170                         }
171                         nStart += nRead;//下一次从哪里开始读取
172                         startPos = nStart;
173 
174                         message.obj = result;//返回的结果
175                         handler.sendMessage(message);
176                     }
177                     progressDialog.cancel();
178                 } catch (IOException e) {
179                     e.printStackTrace();
180                 }
181             }
182         }).start();
183     }
184 }

 四、服务端

 1  [WebMethod(EnableSession = true, Description = "上传文件")]
 2         public int BigFileUploadByBase64String(string base64string, string fileName1)
 3         {
 4             try
 5             {
 6                 string fileName = "D:\\VedioPlayerWeb\\videos\\" + fileName1;
 7                 // 取得文件夹
 8                 string dir = fileName.Substring(0, fileName.LastIndexOf("\\"));
 9                 //如果不存在文件夹,就创建文件夹
10                 if (!Directory.Exists(dir))
11                     Directory.CreateDirectory(dir);
12                 byte[] bytes = Convert.FromBase64String(base64string);
13                 MemoryStream memoryStream = new MemoryStream(bytes, 0, bytes.Length);
14                 memoryStream.Write(bytes, 0, bytes.Length);
15                 if (!File.Exists(fileName))
16                 {
17                     // 写入文件
18                     File.WriteAllBytes(fileName, memoryStream.ToArray());
19                 }
20                 else
21                 {
22                     FileStream fsSource = new FileStream(fileName, FileMode.Append, FileAccess.Write);
23                     fsSource.Write(memoryStream.ToArray(),0, memoryStream.ToArray().Length);
24                     fsSource.Close();
25                 }
26                 //返回数据如果是1,上传成功!
27                 return 1;
28             }
29             catch (Exception ex)
30             {
31                 //返回如果是-1,上传失败
32                 return -1;
33             }
34         }

 

 


 

 

本文是在《使用.NET框架、Web service实现Android的文件上传(一)》的基础上继续编写的,如有疑问请先查看第一篇。本文的代码(包括客户端与服务端)已经上传至GitHub,地址:https://github.com/weifengzz/UploadFile_1

 

posted @ 2015-12-09 18:11  weifengzz  阅读(744)  评论(1编辑  收藏  举报