你的位置:首页 > 操作系统

[操作系统]使用.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 block70       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     @Override100     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       @Override120       public void run() {121         // TODO Auto-generated method stub122         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 block129           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       @Override144       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 block169               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         else21         {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