使用JSON通过多部分请求连接到Android中的REST服务

使用JSON通过多部分请求连接到Android中的REST服务,android,rest,multipart,image-upload,Android,Rest,Multipart,Image Upload,我正在尝试连接到一个REST服务,它接受一个json对象和一个图像,并从图像返回文本(在OCR之后) REST服务的声明请求必须类似于: -----BOUNDARY Content-Type: application/json {"engine":"tesseract"} -----BOUNDARY -----BOUNDARY Content-Disposition: attachment; Content-Type: image/png filename="attachment.txt".

我正在尝试连接到一个REST服务,它接受一个json对象和一个图像,并从图像返回文本(在OCR之后)

REST服务的声明请求必须类似于:

-----BOUNDARY
Content-Type: application/json

{"engine":"tesseract"}
-----BOUNDARY

-----BOUNDARY
Content-Disposition: attachment;
Content-Type: image/png
filename="attachment.txt".

PNGDATA.........
-----BOUNDARY
因此,我参考并修改了代码,当我运行代码时,它会给我以下错误:

W/System.err: java.io.IOException: unexpected end of stream on Connection{192.168.0.102:8080, proxy=DIRECT@ hostAddress=192.168.0.102 cipherSuite=none protocol=http/1.1} (recycle count=0)
以下是我的multipartity.java文件的内容

import java.io.BufferedReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/**
 * For sending Multipart requests: modified for OCR
 *http://www.codejava.net/java-se/networking/upload-files-by-sending-multipart-request-programmatically
 *
 */
public class MultipartUtility {
    private final String boundary;
    private static final String LINE_FEED = "\r\n";
    private HttpURLConnection httpConn;
    private String charset;
    private OutputStream outputStream;
    private PrintWriter writer;

    /**
     * This constructor initializes a new HTTP POST request with content type
     * is set to multipart/form-data
     * @param requestURL
     * @param charset
     * @throws IOException
     */
    public MultipartUtility(String requestURL, String charset)
            throws IOException {
        this.charset = charset;


        boundary = "---BOUNDARY";

        URL url = new URL(requestURL);
        httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setUseCaches(false);
        httpConn.setDoOutput(true); // indicates POST method
        httpConn.setDoInput(true);
        httpConn.setRequestProperty("Content-Type",
                "multipart/related; boundary=" + boundary);
 //       httpConn.setRequestProperty("User-Agent", "CodeJava Agent");
   //     httpConn.setRequestProperty("Test", "Bonjour");
        outputStream = httpConn.getOutputStream();
        writer = new PrintWriter(new OutputStreamWriter(outputStream, charset),
                true);
    }

    /**
     * Adds a form field to the request
     *
     */
    public void addFormField() {
        writer.append(boundary).append(LINE_FEED);
      //  writer.append("Content-Disposition: form-data; name=\"" + name + "\"")
        //        .append(LINE_FEED);
        writer.append("Content-Type: application/json").append(LINE_FEED);
        writer.append(LINE_FEED);
        writer.append("{\"engine\":\"tesseract\"}").append(LINE_FEED);
        writer.append(boundary).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Adds a upload file section to the request
     * @param fieldName name attribute in <input type="file" name="..." />
     * @param uploadFile a File to be uploaded
     * @throws IOException
     */
    public void addFilePart(String fieldName, File uploadFile)
            throws IOException {
        String fileName = uploadFile.getName();
        writer.append(boundary).append(LINE_FEED);
        writer.append("Content-Disposition: attachment;")
                .append(LINE_FEED);
        writer.append("Content-Type: image/png").append(LINE_FEED);
        writer.append("filename="+fileName+".").append(LINE_FEED);
        writer.append(LINE_FEED);


    //adding png data here
        FileInputStream inputStream = new FileInputStream(uploadFile);
        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.flush();
        inputStream.close();

        writer.append(boundary).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Adds a header field to the request.
     * @param name - name of the header field
     * @param value - value of the header field
     */
    public void addHeaderField(String name, String value) {
        writer.append(name + ": " + value).append(LINE_FEED);
        writer.flush();
    }

    /**
     * Completes the request and receives response from the server.
     * @return a list of Strings as response in case the server returned
     * status OK, otherwise an exception is thrown.
     * @throws IOException
     */
    public List<String> finish() throws IOException {
        List<String> response = new ArrayList<>();

      //  writer.append(LINE_FEED).flush();
     //   writer.append("--" + boundary + "--").append(LINE_FEED);

        writer.close();

        // checks server's status code first
        int status = httpConn.getResponseCode();
        if (status == HttpURLConnection.HTTP_OK) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    httpConn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                response.add(line);
            }
            reader.close();
            httpConn.disconnect();
        } else {
            throw new IOException("Server returned non-OK status: " + status);
        }

        return response;
    }
}
导入java.io.BufferedReader;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.IOException;
导入java.io.InputStreamReader;
导入java.io.OutputStream;
导入java.io.OutputStreamWriter;
导入java.io.PrintWriter;
导入java.net.HttpURLConnection;
导入java.net.URL;
导入java.net.URLConnection;
导入java.util.ArrayList;
导入java.util.List;
/**
*用于发送多部分请求:针对OCR修改
*http://www.codejava.net/java-se/networking/upload-files-by-sending-multipart-request-programmatically
*
*/
公共类多机性{
私有最终字符串边界;
私有静态最终字符串行\u FEED=“\r\n”;
专用HttpURLConnection httpConn;
私有字符串字符集;
私有输出流输出流;
私人版画作家;
/**
*此构造函数初始化内容类型为的新HTTP POST请求
*设置为多部分/表单数据
*@param requestURL
*@param字符集
*@抛出异常
*/
公共多功能(字符串请求URL、字符串字符集)
抛出IOException{
this.charset=charset;
边界=“---边界”;
URL=新URL(请求URL);
httpConn=(HttpURLConnection)url.openConnection();
httpConn.setUseCaches(假);
httpConn.setDoOutput(true);//表示POST方法
httpConn.setDoInput(真);
httpConn.setRequestProperty(“内容类型”,
“多部分/相关;边界=”+边界);
//setRequestProperty(“用户代理”、“代码Java代理”);
//httpConn.setRequestProperty(“测试”,“你好”);
outputStream=httpConn.getOutputStream();
writer=新的PrintWriter(新的OutputStreamWriter(outputStream,字符集),
正确的);
}
/**
*将表单字段添加到请求中
*
*/
public void addFormField(){
writer.append(边界).append(换行符);
//writer.append(“内容处置:表单数据;名称=\”“+name+\”“”)
//.append(换行符);
writer.append(“内容类型:application/json”).append(换行符);
writer.append(换行符);
writer.append(“{\'engine\”:\'tesseract\”}”).append(换行符);
writer.append(边界).append(换行符);
writer.flush();
}
/**
*将上载文件节添加到请求中
*中的@param fieldName属性
*@param uploadFile要上载的文件
*@抛出异常
*/
public void addFilePart(字符串字段名,文件上传文件)
抛出IOException{
字符串文件名=uploadFile.getName();
writer.append(边界).append(换行符);
writer.append(“内容处置:附件;”)
.append(换行符);
writer.append(“内容类型:image/png”).append(换行符);
writer.append(“filename=“+filename+”).append(换行符);
writer.append(换行符);
//在此处添加png数据
FileInputStream inputStream=新的FileInputStream(上传文件);
字节[]缓冲区=新字节[4096];
int字节读取=-1;
而((bytesRead=inputStream.read(缓冲区))!=-1){
写入(缓冲区,0,字节读取);
}
outputStream.flush();
inputStream.close();
writer.append(边界).append(换行符);
writer.flush();
}
/**
*向请求添加标题字段。
*@param name-标题字段的名称
*@param value-标题字段的值
*/
public void addHeaderField(字符串名称、字符串值){
writer.append(name+”:“+value).append(LINE\u FEED);
writer.flush();
}
/**
*完成请求并从服务器接收响应。
*@返回字符串列表作为服务器返回时的响应
*状态为OK,否则将引发异常。
*@抛出异常
*/
public List finish()引发IOException{
列表响应=新建ArrayList();
//writer.append(LINE_FEED.flush();
//writer.append(“-”+边界+“-”).append(换行符);
writer.close();
//首先检查服务器的状态代码
int status=httpConn.getResponseCode();
if(status==HttpURLConnection.HTTP\u OK){
BufferedReader reader=新的BufferedReader(新的InputStreamReader(
httpConn.getInputStream());
字符串行=null;
而((line=reader.readLine())!=null){
响应。添加(行);
}
reader.close();
httpConn.disconnect();
}否则{
抛出新IOException(“服务器返回非OK状态:+状态”);
}
返回响应;
}
}
我正在我的MainActivty.java文件中使用此多功能:

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    //OkHttpClient client;
    String serverUrl = "http://192.168.0.102:8080/ocr-file-upload";
    String imgUrl;
    String TAG = "MainAcivity";
    TextView tvMain;
    File uploadFile1;
    String charset = "UTF-8";
    Button btn_make_request;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_make_request = (Button) findViewById(R.id.btn_make_request);
        tvMain = (TextView) findViewById(R.id.tv_main);
       // client = new OkHttpClient();
        imgUrl = Environment
                .getExternalStorageDirectory().toString()+"/ocr_test.png";
        uploadFile1 = new File(imgUrl);




        btn_make_request.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(isStoragePermissionGranted())
                    new UploadImage().execute();
                else
                    Toast.makeText(MainActivity.this, "PERMISSION PROBLEM", Toast.LENGTH_SHORT).show();


            }
        });



    }//edn oncreate

    private class UploadImage extends AsyncTask<String, Void, String> {


        @Override
        protected String doInBackground(String... strings) {
            Log.v(TAG, "IN DO IN BACKGROUND");
            //   upload(serverUrl);
             doMultipartOcr();
            //doRequest();
            return null;
        }
    }


    public void doMultipartOcr(){
        try {
            MultipartUtility multipart = new MultipartUtility(serverUrl, charset);
           // multipart.addHeaderField("Content-Type", "multipart/related");
           // multipart.addHeaderField("boundary=", "---BOUNDARY");
            multipart.addFormField();
            multipart.addFilePart("fileUpload", uploadFile1);
            List<String> response = multipart.finish();
            for (String line : response) {
                //TODO: display Output
                tvMain.setText(tvMain.getText() + "\n" + line);
            }
        } catch (IOException ex) {
            //TODO: display error
            Log.v(TAG, ex.getMessage());
            ex.printStackTrace();
        }
    }

    public  boolean isStoragePermissionGranted() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {
                Log.v(TAG,"Permission is granted");
                return true;
            } else {

                Log.v(TAG,"Permission is revoked");
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                return false;
            }
        }
        else { //permission is automatically granted on sdk<23 upon installation
            Log.v(TAG,"Permission is granted");
            return true;
        }


    }
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
            Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
            //resume tasks needing this permission
        }
    }


}
导入android.Manifest;
导入android.content.pm.PackageManager;
导入android.os.AsyncTask;
导入android.os.Build;
导入android.os.Environment;
导入android.support.v4.app.ActivityCompat;
导入android.support.v7.app.AppActivity;
导入android.os.Bundle;
导入android.util.Log;
导入android.view.view;
导入android.widget.Button;
导入android.widget.TextView;
导入android.widget.Toast;
导入java.io.File;
导入java.io.IOException;
导入java.util.List;
公共类MainActivity扩展了AppCompatActivity{
//Okhttp客户端;
字符串serverUrl=”http://192.168.0.102:8080/ocr-文件上传”;
字符串imgUrl;