Android implementation of file breakpoint upload

Source: Internet
Author: User
Tags thread class

In the Android development process, file uploads are very common. But the file's breakpoint continues to be rare. Because Android is requesting the server through the HTTP protocol, HTTP itself does not support file breakpoint uploads. However, the HTTP support file breakpoint download, you can use the HTTP file breakpoint download principle to achieve the file breakpoint upload, file breakpoints download relatively simple, the main steps are as follows
(1) Open the service, download the file through the service background
(2) conn.getcontentlength (); Gets the length of the file to download, and creates a file of the corresponding size
(3) Set the start byte and end byte of the file we want to download by using the Range field. Http.setrequestproperty ("Range", "bytes=" +
Startpos + "-" + endpos)//Note Format Center Plus "-"
(4) Save the progress of our download through Sqllite so that the breakpoint can be downloaded when the task is restarted
(5) Update the progress bar by broadcasting the progress of the download to the main thread.
(6) using the Randomaccessfile seek method, skipping the downloaded bytes to write the downloaded bytes to the file
Through these six steps can achieve a simple breakpoint continuation, of course, single-thread download performance is poor. In the final optimization process, we also need to add multithreaded downloads to improve our download efficiency. OK file disconnection Download this is not the point we want to talk about, the next is the core content.
Uploading files is a time-consuming operation for Android and cannot be done in the main thread. Still need to use the service to complete. But there is no range field to pass in the start and end bytes we want to upload. How this should be done, which requires the file upload, our server to make a corresponding change. Upload the file, the size of the file name and size as parameters uploaded to the server, so that the server records the size of the file to upload. During the upload process, the server will record the number of bytes that have been uploaded. At the breakpoint, the mobile end does not need to record the file's uploaded size, but first to request the server to get the number of bytes uploaded, the mobile side does only skip the corresponding number of bytes to read the file. It's important to say here how Android interacts with the server when it passes HTTP requests. When the mobile end gets a link to the server, the data is passed through the stream, and when the file is read by the mobile end, it is not cached in the stream, but it is cached on the Android side, while the Android memory is limited and the memory overflows when uploading large files. In the stream to write data, the server can not be timely to get the data in the stream, but when the mobile end to submit the server can make response, mobile end is based on response to determine whether the file upload success. This will be a problem, Android to submit files in real time, responsible for the memory overflow caused Cheng crash. When uploading files, you must first check the file to avoid duplicate file uploads. For files that are uploaded repeatedly, the server will only be able to associate the uploaded file with the user. The checksum of the file is MD5 checksum, and the MD5 checksum is time-consuming and therefore more threading. It is OK to update the progress bar by using the broadcast, but you can also use handler to update the progress bar. This all depends on personal preference. So the file breakpoint upload ideas have.
(1) Open the service, through the service background inspection files and upload files
(2) The number of uploaded bytes of the file in the response of the inspection file
(3) using the Randomaccessfile seek method, skipping the uploaded bytes to read the file
(4) Multi-file upload through the sqllite to save the state of the file, for the uploaded file to set the status value has been uploaded or deleted in the database
(5) Update the progress bar by broadcasting the progress of the download to the main thread.
The following is the main code for file breakpoint uploads

  @Override public void OnClick (View v) {switch (V.getid ()) {case R.id.tv_shangchuan:
                The selected file path is passed through intent to the service List_filepath.clear () when the upload is started;
Pass the path of the file into service int file_count = Map_check_file.size ();
                L.i ("-----count" +file_count);
                    if (file_count==0) {T.showshort (this, "Empty folder cannot be uploaded");
                Return
                } loading_dialog1.show ();
                    For (map.entry<string, file> entry:map_check_file.entrySet ()) {File value = Entry.getvalue ();
                List_filepath.add (Value.getabsolutepath ());
                } Intent Intent_service = new Intent ();
                Intent_service.setaction (Mainactivity.action_start);
                Intent_service.setpackage (Getpackagename ());
              Intent_service.putextra ("File_list", (Serializable) list_filepath);  Getapplication (). StartService (Intent_service);
            Break Case R.id.tv_lixian:if (map_check_file.size ()!= 0) {for (map.entry<string, file& Gt Entry:map_check_file.entrySet ()) {//Add the uploaded files to the database Filedaoimp.insertdata (
                    Entry.getvalue (). GetAbsolutePath ());
                    } Fragment Fragmentbyid = Manager.findfragmentbyid (r.id.fl_director_activity);
                    Filefragment filefragment = (filefragment) Fragmentbyid;
                    if (filefragment!= null) {sendmessagetofragment (filefragment);
                    } t.showshort (This, "joined offline");
                Rl_director_bottom.setvisibility (View.gone);
                else {T.showshort (this, "Empty folder cannot be added offline");
        } break; }
    }

Because there are offline features in the project, it is posted together, offline implementation is also simpler. When the user clicks Offline, the path of the offline file is entered into the database, and then the network status is judged by broadcast, and when WiFi is available, the file is not downloaded and the service download is opened. The code for the
Service is as follows:

public class Downloadservice extends Service implements Apicallback {private Handler Handler = new Handler () {
                    @Override public void Handlemessage (msg) {switch (msg.what) {Case 1:
                    Downloadtask = new Downloadtask (downloadservice.this);
                    Downloadtask.download ();
            Break

    }
        }
    };
    public static final String Receivi = "UpdateProgress";
    The thread that downloads the file is private downloadtask downloadtask = null;
    File Breakpoint upload Database management class Filedaoimp Filedaoimp = new Filedaoimp (downloadservice.this);
    Boolean isfirst = true;

    list<string> List_file_path = new arraylist<> ();
    @Nullable @Override public IBinder onbind (Intent Intent) {return null;
            @Override public int Onstartcommand (Intent Intent, int flags, int startid) {if (Intent!= null) { if (MainActivity.ACTION_START.equals (Intent.getaction ())) {downloadtask.ispause = false;
                String Loading_shangchuan = Intent.getstringextra ("Loading_shangchuan");  if (Loading_shangchuan!= null && loading_shangchuan.equals ("Loading_shangchuan")) {Isfirst =
                    False
                    New Initthread (). Start ();
                Return Super.onstartcommand (Intent, flags, Startid);
                } List_file_path = (list<string>) Intent.getserializableextra ("File_list");
                Isfirst = true;
                LOG.I ("main", "--------list---Service--------------" + list_file_path.size ());
            Initializes the thread new Initthread (). Start ();
                    else if (MainActivity.ACTION_STOP.equals (Intent.getaction ()) {if (downloadtask!= null) {
                    Downloadtask.ispause = true;
                Downloadtask = null; } else if (MainActivity.ACTION_CANCEL.equals (inTent.getaction ()) {downloadtask.ispause = true;
                Downloadtask = null;
                Filedaoimp.deletdatefiletask ();
            Filedaoimp.deletefileurl (); }///Start_no_sticky//start_sticky default call return Super.onstartcommand (intent, flags, ST
    ArtID); 
                ///Initial session file thread class Initthread extends thread {@Override public void run () {if (Isfirst) { for (int i = 0; i < list_file_path.size (); i++) {File File = new file (list_file_p
Ath.get (i));
                    L.i ("-------file-------------" + file.length ());
                    FileInfo FileInfo2 = null;
                            try {if (!file.isdirectory ()) {//Save selected files to the database FileInfo2 = new FileInfo (2, File.getabsolutepath (), File.getname (), File.length (), 0, md5util.getfilemd5string (file)
                  ;          Filedaoimp.insertfileurl (Fileinfo2.geturl (), Fileinfo2.getlength (), Fileinfo2.getmd5 (), FileInfo2.getFileName ())
                        ;
                    } catch (IOException e) {e.printstacktrace ();

        }} handler.obtainmessage (1). Sendtotarget ();
 }
    }
}

//File upload thread, upload file in 5M fragment. Here's how Android can no longer cache locally.

/** * Created by Zhoukai on 2016/5/3.
 *//int fixedlength = (int) fstream.getchannel (). Size (); 
 *//known output stream length with Setfixedlengthstreamingmode () *//position output stream length with Setchunkedstreamingmode ()
 *//Con.setchunkedstreamingmode (block size);                    *//If the above two methods are not used, then the output is cached locally, then the outofmemory *//sets the size of the fixed stream when writing to the output stream larger than 40M files *//
 Con.setfixedlengthstreamingmode (fixedlength);
 *//Con.setfixedlengthstreamingmode (1024 * 1024*20);
    * * Public class Downloadtask {private context context;
    Private Filedaoimp Filedaoimp;
    public static Boolean ispause = false;
    Private long file_sum = 0;
    String Isexisturl = "Http://123.56.15.30:8080/upload/isExistFile";
    String ActionURL = "Http://123.56.15.30:8080/upload/uploadFile";
    private int finishedlength;
        Public Downloadtask {this.context = context; Filedaoimp = new Filedaoimp (cOntext);
    public void Download () {new Downthread (). Start ();
        Class Downthread extends Thread {private double load_lenth = 0;
        String end = "\ r \ n";
        String Twohyphens = "--";
        String boundary = "* * *"; @Override public void Run () {//not uploaded file list<fileinfo> List = Filedaoimp.queryfilebys
            Tate ();
            LOG.I ("main", "--------list--database---------------" + list.size ());
            int sum_filelength = (int) filedaoimp.getlengthbystate (0);
            if (list.size () = = 0) {return;
            } Intent Intent = new Intent ();
            Intent.setaction (Downloadservice.receivi);
            int nsplitter_length = 1024 * 1024 * 5;
                for (int i = 0; i < list.size (); i++) {int file_length = (int) list.get (i). GetLength ();
int count = file_length/nsplitter_length + 1; L.I ("-------------------MD5------------"+ list.get (i). GETMD5 ());

L.i ("------------------fileName------------" + list.get (i). GetFileName ());
                ---------------------Verify file--------------------------------------------------URL realurl = null;
                InputStream in = null;
                HttpURLConnection conn = null;
                    try {realurl = new URL (Isexisturl);
                    conn = (httpurlconnection) realurl.openconnection ();
                    Conn.setrequestproperty ("Accept", "*/*");
                    Conn.setrequestproperty ("Connection", "keep-alive"); Conn.setrequestproperty ("User-agent", "mozilla/4.0" (compatible; MSIE 6.0; Windows NT 5.1;
                    SV1) ");
                    Conn.setrequestmethod ("POST");
                    Conn.setchunkedstreamingmode (1024 * 1024 * 10);
                    Infinity Timeout conn.setreadtimeout (0);
      Conn.setconnecttimeout (0);              Conn.setdoinput (TRUE);
                    Conn.setdooutput (TRUE);
                    PrintWriter pw = new PrintWriter (Conn.getoutputstream ()); Pw.print ("userid=" + apputils.getusername (context) + "&md5=" + list.get (i). GETMD5 () + "&am
                    P;did= "+ getdid () +" &name= "+ list.get (i) GetFileName () +" &size= "+ list.get (i)-getlength ());
LOG.I ("main", "-------------userId---------" + apputils.getusername (context));
LOG.I ("main", "-------------MD5---------" + list.get (i)-getMd5 ());
LOG.I ("main", "-------------did---------" + Getdid ());
LOG.I ("main", "-------------name---------" + list.get (i). GetFileName ());
                    LOG.I ("main", "-------------size---------" +list.get (i). GetLength ());
                    Pw.flush ();
                       Pw.close (); /* Get response content/in = Conn.getinputStream ();
                    int ch;
                    StringBuffer StringBuffer = new StringBuffer ();
                    while (ch = in.read ())!=-1) {stringbuffer.append ((char) ch);
                    String json = stringbuffer.tostring ();
                    Jsonobject jsonobject = new Jsonobject (JSON);
                    Boolean issuccess = Jsonobject.optboolean ("Success"); if (issuccess) {int lengths = Jsonobject.optjsonobject ("info"). Optjsonobject ("file"). Optint ("Leng
                        Th ");
                        Finishedlength = lengths; if (finishedlength = = List.get (i). GetLength ()) {filedaoimp.deletefilebymd5 list.get (i). getMd5
                            ());
                            Filedaoimp.deletefilebypath (List.get (i). GETURL ()); if (i = = List.size ()-1) {Intent.putextra ("Progress", (Load_lenth * 100/(double) sum_filelength));
                                Intent.putextra ("state", "success");
                            Context.sendbroadcast (Intent);
                        } continue;
                    } log.i ("Main", "-----length_finished------" + finishedlength);

                The catch (Exception Eio) {log.i ("main", "-----Exception------" + eio.tostring ());
                //---------------------Upload file-------------------------------------------------- for (int j = 0; J < Count; J +) {try {File file = new file (list.ge
                        T (i). GETURL ());
                        URL url = new URL (actionurl);
                        HttpURLConnection con = (httpurlconnection) url.openconnection ();
                        Con.setchunkedstreamingmode (1024 * 1024 * 10);
           Infinity Timeout             Con.setreadtimeout (0);
            Con.setconnecttimeout (0);
                        /* Allow input, Output, do not use cache */Con.setdoinput (TRUE);
                        Con.setdooutput (TRUE);
            Con.setusecaches (FALSE);
            /* Set the Transmitting Method=post * * Con.setrequestmethod ("POST");
                        /* Setrequestproperty * * Con.setrequestproperty ("Connection", "keep-alive");//Establish long connection        Con.setrequestproperty ("Charset", "UTF-8"); Encoding format con.setrequestproperty ("Content-type", "Multipart/form-data ; boundary= "+ boundary);/form Submit file DataOutputStream ds = new DataOutputStream (Con.getoutputstream ())
                        ;
                        Add parameter StringBuffer sb = new StringBuffer ();
                     map<string, string> params_map = new hashmap<> ();   Params_map.put ("Nsplitter", "3");
                        Params_map.put ("MD5", List.get (i). GETMD5 ());
                        Params_map.put ("DId", Getdid ());
                        Params_map.put ("UserId", Apputils.getusername (context));
                        Params_map.put ("Name", File.getname ());
                        Params_map.put ("from", Finishedlength + "");
                        LOG.I ("main", "-------------userId----Upload-----" + apputils.getusername (context)); if (finishedlength + nsplitter_length > File_length) {params_map.put ("to", File_length + "
                        ");
                        else {params_map.put ("to", (Finishedlength + nsplitter_length) + "");
                        } params_map.put ("Size", List.get (i). GetLength () + "");
            Add parameter for (map.entry<string, string> entries:params_map.entrySet ()) {                Sb.append (Twohyphens). Append (Boundary). Append (end);//Delimiter sb.append ("Content-di Sposition:form-data;
                            Name= "+ entries.getkey () + end); Sb
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.