Implementing file upload in Android

Keywords: Android Java network JSON

This example is a small example that I used in my project a year ago, using the HttpURLConnection that Android comes with to upload files. Online information on this aspect is not too much, there are two examples are not very detailed, I used in the development, feel very practical, share out, hoping to help all friends, limited by the level, examples if there are fallacies, I hope you God criticism and correction, this example is suitable for the project of the file upload is relatively small, when the document on. It's better to use frameworks (such as okhtp) when transmitting more.
Originally, I wanted to tidy up just after the winter vacation. Because I came home late a year ago, there were a lot of things before and after the year, until now I have no time to tidy up. No more nonsense, go directly to the code: (code I cut out from the project, there may be errors, the problem will not be too big, very good to correct)

import android.os.Handler;
import android.os.Message;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class ArrivateUpload extends Thread {

    private final String BOUNDARYSTR = "--------aifudao7816510d1hq";
    private final String END = "\r\n";
    private final String LAST = "--";
 
    private String data;//Form Data
    private FileInputStream fis;//File input stream
    private Handler handler;

    public ArrivateUpload(String data, FileInputStream fis, Handler handler) {
        this.data = data;
        this.handler = handler;
        this.fis=fis;
    }

    @Override
    public void run() {
        try {
            URL httpUrl=new URL(urlStr);
            HttpURLConnection connection= (HttpURLConnection) httpUrl.openConnection();
            connection.setRequestMethod("POST");//Must be post
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-type", "multipart/form-data;boundary=" + BOUNDARYSTR);//Fixed format
            DataOutputStream dos=new DataOutputStream(connection.getOutputStream());
            StringBuffer sb=new StringBuffer();
  /**
 * Write text data
 */

            sb.append(LAST+BOUNDARYSTR+END);
            sb.append("Content-Disposition: form-data; name=\"data\""+END+END);
            sb.append(data+END);//content
 /**
 * Loop Write File
 */
sb.append(LAST+BOUNDARYSTR+END);
sb.append("Content-Disposition:form-data;Content-Type:application/octet-stream;name=\"file\";");
            sb.append("filename=\""+"map_image.png"+"\""+END+END);
            dos.write(sb.toString().getBytes("utf-8"));
            if (fis != null) {
                byte[] b=new byte[1024];
                int len;
                while ((len=fis.read(b))!=-1){
                    dos.write(b,0,len);
                }
                dos.write(END.getBytes());
            }
            dos.write((LAST+BOUNDARYSTR+LAST+END).getBytes());
            dos.flush();
            sb=new StringBuffer();
            if (connection.getResponseCode()==200) {//Request successful
                BufferedReader br=new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                while ((line=br.readLine())!=null){
                    sb.append(line);
                }
                Message msg=Message.obtain();
                JSONObject object=new JSONObject(sb.toString());
                handler.sendMessage(msg);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

Talk about the idea of implementation: using the HttpURLConnection provided in Android system, using the multipart protocol in http to upload files. HttpUrlConnection should not be much to say (unfamiliar students go to Google to learn about HttpURLConnection and http protocol), just say a few points, request mode is set to POST, open the input and output stream (this seems to be open by default, or set to true is more assured)
Focus on the multipart protocol, because the ordinary http post protocol uses too simple delimiters, uploading files will cause file segmentation ambiguity, so the multipart protocol must be used. Write a simple HTML form file upload example, learn by comparison.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>upload</title>
</head>
<body>
<form action="a.php" method="post" enctype="multipart/form-data">
    <input type="text" name="data"/>
    <input type="file" name="file">
    <input type="submit">
</form>
</body>
</html>

In the browser, we can spell out the multipart protocol by debugging the browser. The browser will report 404. A. PHP is not found, regardless of it, this is not the focus of our attention. Here's the browser details

Paste_Image.png

A separator is defined in one place. The separator is as complex as possible to avoid conflicts with the characters in the file. Attention, there are big pits ahead, pay attention to the throttle under your feet, the old driver will roll over if he is not careful. By careful comparison, you will find that 2, 3, 4 and 1 are different. 2, 3, 4 are two more "-" than 1. Be careful. That's why we need to add "-" when we use boundary. sb.append(LAST+BOUNDARYSTR+END); 4 places, the end of the whole body to add a "--", there is no why, the agreement is so stipulated.

Each line ends with a " r\n" and the second line ends with two "\ r\n" before the data file begins. A blank line is found in front of the data file in the comparison chart. It is also very important to pay attention to the problem of quotation marks (""), if the quotation marks fail, upload will fail, and this error is not easy to find. File writing needs to be written in an input stream loop

sb.append("Content-Disposition:form-data;Content-Type:application/octet-stream;name=\"file\";");  //Before name is fixed, here name is needed when the server receives it.
sb.append("filename=\""+"map_image.png"+"\""+END+END); // It doesn't matter if the value of filename here is written casually, but it must be there. It doesn't cause the upload to fail.
dos.write(sb.toString().getBytes("utf-8"));
            if (fis != null) {
                byte[] b=new byte[1024];
                int len;
                while ((len=fis.read(b))!=-1){
                    dos.write(b,0,len);
                }
                dos.write(END.getBytes());
            }
            dos.write((LAST+BOUNDARYSTR+LAST+END).getBytes());
            dos.flush();

Share another debugging technique. Our program runs on Android. We can't debug it as we do in browsers. So it's very necessary to open the package (genymation has its own package grabber, familiar with linux can be used directly). Run the program on the simulator, the computer opens the package grabber, grabs a data packet every time it uploads, and analyses the data package if something goes wrong. Compared with the browser format, debugging is not too sour. The content uploaded once was a bit complicated, and the debugging was incorrect all the time. Finally, it was done by grabbing the comparisons of the packages. I use wireshark, which is too powerful to install drivers directly on the network card, as long as the data can be grasped through the network card (imaginative students can use it to do some bad things here omit a thousand words...). Another thing to note is that Wireshark can't grab data packets with ip 127.0.0.1 (using local computers as servers), because the data can't be grabbed without a network card.
Due to the limited level and the rush of time, if there are any fallacies, please also ask the gods to criticize and correct them.

Posted by GodzMessanja on Sat, 26 Jan 2019 11:12:15 -0800