Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Resume file uploading process in Android?

I am uploading a file on server using this code, But I want such a functionality: if it stops due to lost a network or any other interruption during the process, then it shouldn't be start uploading from beginning at second time. response from server is also customizable. is it possible in android? what approach should I use to do this? please guide me. and if possible please suggest me any sample piece of code.

Thanks!

public String uploadFile(InputStream is) {
    HttpURLConnection conn;
    String jsonResponse = "";
    int streamSize = 0;
    DataOutputStream dos = null;
    DataInputStream inStream = null;
    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary = "*****";
    int bytesAvailable, bufferSize;
    byte[] buffer;

    String urlString = "*******<My URL>*******";
    try {
        // ------------------ CLIENT REQUEST
        // FileInputStream fileInputStream = new FileInputStream(new
        // File(selectedPath) );

        // open a URL connection to the Servlet

        URL url = new URL(urlString);
        // Open a HTTP connection to the URL
        conn = (HttpURLConnection) url.openConnection();
        // Allow Inputs
        conn.setDoInput(true);
        // Allow Outputs
        conn.setDoOutput(true);
        // Don't use a cached copy.
        conn.setUseCaches(false);

        conn.setChunkedStreamingMode(0);
        // Use a post method.
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Content-Type",
                "multipart/form-data;boundary=" + boundary);
        dos = new DataOutputStream(conn.getOutputStream());

        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"wheeze_file\";filename="
                + fileName + lineEnd);
        dos.writeBytes(lineEnd);

        // create a buffer of maximum size
        bytesAvailable = is.available();
        streamSize = bytesAvailable;
        bufferSize = 2048;
        buffer = new byte[bufferSize];
        // read file and write it into form...
        int i = 0;
        int length = 0;
        while ((length = is.read(buffer, 0, bufferSize)) > 0) {
            if (isCancelled()) {
                Toast.makeText(getApplicationContext(), "Cancelled",
                        Toast.LENGTH_SHORT).show();
                return null;
            }
            dos.write(buffer, 0, length);
            bytesAvailable = is.available();

            // bufferSize = Math.min(bytesAvailable, maxBufferSize);

            publishProgress(streamSize, bytesAvailable);
            // Log.v("Progress",""+streamSize+" : "+bytesAvailable);
        }
        // send multipart form data necesssary after file data...
        dos.writeBytes(lineEnd);

        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"data[authentication][email]\""
                + lineEnd);
        dos.writeBytes(lineEnd);
        dos.writeBytes(username);
        dos.writeBytes(lineEnd);
        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"data[authentication][password]\""
                + lineEnd);
        dos.writeBytes(lineEnd);
        dos.writeBytes(enc_password);
        dos.writeBytes(lineEnd);
        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"method\""
                + lineEnd);
        dos.writeBytes(lineEnd);
        dos.writeBytes("uploadWheezeFile");
        dos.writeBytes(lineEnd);
        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
        // close streams
        Log.e("Debug", "File is written");

        // Log.v("Conn status", "Disconnected");

    } catch (MalformedURLException ex) {
        ex.printStackTrace();
        Log.e("Debug", "MURLExerror: " + ex.getMessage(), ex);
    } catch (IOException ioe) {
        ioe.printStackTrace();
        Log.e("Debug", "IOEx error: " + ioe.getMessage(), ioe);
        uploadTask.cancel(true);
        return null;
    } finally {
        try {
            is.close();
            dos.flush();
            dos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    // ------------------ read the SERVER RESPONSE
    try {
        inStream = new DataInputStream(conn.getInputStream());

        if ((jsonResponse = inStream.readLine()) != null) {
            Log.e("Debug", "Server Response " + jsonResponse);

        } else {
            jsonResponse = "";
        }

        inStream.close();
        conn.disconnect();
        //
    } catch (IOException ioex) {
        ioex.printStackTrace();
        Log.e("Debug", "error: " + ioex.getMessage(), ioex);
    }

    return jsonResponse;
}
like image 674
Jignesh Ansodariya Avatar asked Dec 14 '12 04:12

Jignesh Ansodariya


1 Answers

If the receiving server supports it, you can use the Content-Range header to identify a resuming upload. The Google-Drive API supports it. If you roll your own, I'd follow the pattern Google uses:

  • Begin upload and get a session identifier.
  • When upload is interrupted, wait until internet is available to resume.
  • When resuming upload, first inquire of the server how many bytes it has received. (*)
  • Resume upload with the next byte after the server's status.

(*) Note that when I rolled my own before, I added an encoded response from the server with the last KB of upload, just to verify it wasn't corrupted in transfer. However, I've never, in production, seen a case where a server had received corrupt data.

like image 76
323go Avatar answered Oct 06 '22 01:10

323go