отправка телефона с захваченным изображением на сервер localhost flask с помощью запроса Volley, состоящего из нескольких частей; получение java.net.socketexception ошибка прерывания канала

#android #flask #server #android-volley

#Android #flask #сервер #android-volley

Вопрос:

Я пытаюсь создать приложение для Android, которое отправляет изображение, полученное с помощью телефона, на сервер локального хоста, работающий на flask. Я пытаюсь сохранить качество изображения, поскольку я буду выполнять некоторую обработку изображений в фоновом режиме, поэтому я использую многосоставный запрос Volley. Но поскольку я отправляю строку растрового изображения в кодировке base64 в качестве одного параметра, я получаю сообщение об ошибке из сокета, поскольку канал java.net.socketexception не работает.

Я уже пытался уменьшить размер изображения, я также попытался просто отправить строку «hi» вместо закодированного растрового изображения. Когда я это сделал, я получил ответ типа «E / Volley: [80295] BasicNetwork.performRequest: неожиданный код ответа 500».

  public byte[] getFileDataFromDrawable(Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 50, byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }

    private void uploadBitmap(final Bitmap bitmap) {

        final String tags = "image";
        String url="http://192.168.43.36:5000/recog";
        VolleyMultipartRequest volleyMultipartRequest = new VolleyMultipartRequest(Request.Method.POST, url,
                new Response.Listener<NetworkResponse>() {
                    @Override
                    public void onResponse(NetworkResponse response) {
                        try {
                            JSONObject obj = new JSONObject(new String(response.data));
                            Toast.makeText(getApplicationContext(), obj.getString("message"), Toast.LENGTH_LONG).show();
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
                    }
                }) {


            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                String imgString = Base64.encodeToString(getFileDataFromDrawable(bitmap),
                        Base64.NO_WRAP);
                params.put("content", imgString);
//                params.put("content","hi");
                return params;
            }


//            @Override
//            protected Map<String, byte[]> getByteData() {
//                Map<String, byte[]> params = new HashMap<>();
//                params.put("content", getFileDataFromDrawable(bitmap));
//                return params;
//            }
        };


        Volley.newRequestQueue(this).add(volleyMultipartRequest);
    }
 

Код, который я использую в файле flask, выглядит следующим образом:-

 @app.route("/recog", methods=["POST"])
def get_face():

    json1= request.get_json()
    s=json1['content']

    return jsonify(message="Done")
 

Я ожидаю, что base64 будет декодирован в файле flask и сохранен как изображение на локальном устройстве.

Ответ №1:

когда вы печатаете s в соответствии с печатью (ами), что у вас есть?. Это серия строк в кодировке base64

В python 2.7

 import base64
@app.route("/recog", methods=["POST"])
def get_face():

    json1= request.get_json()
    s=json1['content']

    fh = open("imageToSave.png", "wb")
    fh.write(s.decode('base64'))
    fh.close()

    return jsonify(message="Done")
 

или вы можете попробовать

 import base64
@app.route("/recog", methods=["POST"])
def get_face():

    json1= request.get_json()
    s=json1['content']

    with open("imageToSave.png", "wb") as fh:
         fh.write(s.decode('base64'))

    return jsonify(message="Done")
 

Как для Python 2.7, так и для Python 3.x вы также можете попробовать

 import base64
with open("imageToSave.png", "wb") as fh:
     fh.write(base64.decodebytes(s))
 

или вы можете попробовать

 with open("imageToSave.png", "wb") as fh:
     fh.write(base64.decodebytes(s.encode()))
 

Помните: всегда проверяйте свой код, чтобы избежать сообщения об ошибке идентификации

Комментарии:

1. Спасибо. Использование request.get_data() давало мне raw в виде байтов, затем я использовал werkzeug.datastructures, чтобы перевести мои данные в словарную форму. Теперь я могу получить доступ к точной строке.

2. мой ответ также будет работать, как только вы получите свое изображение из словаря данных

3. Да, первоначальная ошибка, которую я получал, заключалась в том, что flask не смог правильно собрать отправленные на него данные.

4. значит ли это, что мое решение решило вашу проблему. почему вы не принимаете это как ответ

5. Я спросил, знает ли кто-нибудь, почему я получаю эту ошибку, и в вашем ответе показаны различные методы сохранения данных в изображении. Ошибка заключалась в том, что я пытался получить данные, которые не были отправлены в формате json в виде объекта json, из-за чего я не получал никаких данных на стороне моего сервера. Это было решено с помощью структуры данных werkzeug для получения данных. Извините, если говорить прямо, но ваш ответ не был решением вопроса, который я задал, я поблагодарил вас за то, что вы ответили.

Ответ №2:

Ребята, я решил проблему. Проблема возникла из-за того, что я пытался получить доступ к форме / многочастным данным, отправленным клиентом через request.get_json(), что неверно. Вместо этого я использовал werkzeug.datastructures для преобразования данных в словарь и доступа к необходимым частям.

Мой текущий код в flask выглядит следующим образом:

 from werkzeug.datastructures import ImmutableMultiDict

@app.route("/recog", methods=["POST"])
def get_face():

    data = dict(request.form)
    img=data['content']
    imgdata = base64.b64decode(img)
    filename = 'some_image.jpg'  
    with open(filename, 'wb') as f:
      f.write(imgdata)
    return jsonify(message="Done")