【问题标题】:Upload an image to Microsoft Computer Vision API through volley on android using octet-stream使用 octet-stream 在 android 上通过 volley 将图像上传到 Microsoft Computer Vision API
【发布时间】:2018-07-17 02:15:02
【问题描述】:

我一直在尝试在 android 上使用 volley 向 Microsoft 计算机视觉 API 发出请求,但我想从手机上传图像,而不仅仅是发送 url。来自 API (https://westcentralus.dev.cognitive.microsoft.com/docs/services/56f91f2d778daf23d8ec6739/operations/56f91f2e778daf14a499e1fa) 的引用说将 Content-Type 放在 application/octet-stream 上,并且在正文中它只是说“[二进制图像数据]”。 我尝试将图像作为字节数组(byte [])发送,但我不断收到响应 400(代表 InvalidImageFormat 或 Size)。 如果我使用 url 方法,它可以正常工作,但我需要上传图片。

This is the only imformation that the documentation gives

这是我一直在使用的代码:

String URL = "https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Categories&language=en";
            StringRequest apiRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    RespuestaApi.setText("Respuesta: " + response);
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {

                    RespuestaApi.setText("Error: " + error.toString());
                }
            }){
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    HashMap<String, String> headers = new HashMap<>();
                    headers.put("Content-Type", "application/octet-stream");
                    headers.put("Ocp-Apim-Subscription-Key", SubKey);
                    return headers;
                }
                @Override
                public byte[] getBody() throws AuthFailureError {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImgTemp.compress(Bitmap.CompressFormat.JPEG, 50, baos);
                    byte[] imageBytes = baos.toByteArray();
                    return imageBytes;
                }

            };
            VolleySingleton.getInstancia(PruebaApi.this).agregarACola(apiRequest);

顺便说一下,我的位图工作正常。 这是logcat给我的错误:

 E/Volley: [41310] BasicNetwork.performRequest: Unexpected response code 400 for https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Categories&language=en

This is the reference for the response

那么,最后,我必须做些什么才能发送 api 所需的正确图像格式?

提前谢谢你。

【问题讨论】:

    标签: android computer-vision byte android-volley


    【解决方案1】:

    使用retrofit 来做到这一点。我也遇到了同样的错误,但最后我设法让它工作。

    添加 retrofit 依赖项。

    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.5.0'
    

    现在回到如何上传它。

    创建一个实例。

    interface ServiceToCall {
        @Headers({
                "Content-Type: application/octet-stream",
                "Ocp-Apim-Subscription-Key: c6e79ef6f90xxxxxx6743xxx1778be5"
        })
        @POST("describe/")
        Call<ResponseBody> postImage(@Body RequestBody body);
      }
    

    现在,您需要将文件(必须上传的图像文件)传递给请求。为此,首先您需要将该文件存储在某处。

    这将是我的onActivityResult 函数。

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    
        if (resultCode == Activity.RESULT_OK) {
            newImageFile = new File(Environment.getExternalStorageDirectory().toString());
            //Uri fileUri = data.getData();
            for (File temp : newImageFile.listFiles()) {
                if (temp.getName().equals("image.jpeg")) {
                    newImageFile = temp;
                    Bitmap thumbnail = BitmapFactory.decodeFile(newImageFile.getAbsolutePath());
                    imageHolder.setImageBitmap(thumbnail);
                }
    
            }
        }
    }
    

    newImageFile 是我的文件。现在为了上传它,我将调用另一个函数。

    private static final String uriBase_retrofit = "https://westcentralus.api.cognitive.microsoft.com/vision/v2.0/";:这是网址。

    public void testRetroFit(Context context, File t) {
    
        //System.out.println("File to be uploaded is : "+filetoupload.toString());
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
    
        // Change base URL to your upload server URL.
        ServiceToCall service = new Retrofit.Builder().baseUrl(uriBase_retrofit).client(client).build().create(ServiceToCall.class);
    
        File file = new File(String.valueOf(t));
        stringname = file.getAbsolutePath();
        System.out.println("Absolute path is : " + file.getAbsolutePath());
        RequestBody te = RequestBody.create(MediaType.parse("application/octet-stream"),file);
        retrofit2.Call<okhttp3.ResponseBody> req = service.postImage(te);
        req.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
                try {
                    String abc = response.body().string();
                    System.out.println("response is : " + response.body().string());
                    System.out.println("Legth is : "+abc.length()+"and value is : "+abc);
                    JSONObject output = new JSONObject(abc);
                    JSONObject des = output.getJSONObject("description");
                    JSONArray cap = des.getJSONArray("captions");
                    JSONObject cap_description = cap.getJSONObject(0);
                    String cap_textres = cap_description.getString("text");
                    Double cap_conf = cap_description.getDouble("confidence");
                    result_api.setText("Result is : "+cap_textres);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                System.out.println("raw is : "+response.raw());
            }
    
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                t.printStackTrace();
            }
        });
    }
    

    这个对我有用。

    附言费尽周折才知道response.body().string() 只能使用一次。

    【讨论】:

      猜你喜欢
      • 2020-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      • 2019-04-14
      相关资源
      最近更新 更多