首页 > 解决方案 > 改造未正确接收响应

问题描述

我正在尝试将图像作为 base64 发送到节点服务器并接收另一个图像作为 base64 作为响应。在节点服务器中,图像保存在服务器目录中,并在完成 python 文件执行后发送响应。

将 Retrofit 与 kotlin 一起使用时出现超时错误。当我使用 Postman 时,一切正常。

这是改造创建代码:

var  okHttpClient: OkHttpClient =  OkHttpClient.Builder()
    .readTimeout(10, TimeUnit.MINUTES)
    .writeTimeout(10,TimeUnit.MINUTES)
    .connectTimeout(2,TimeUnit.MINUTES)
    .build();
public val retrofit = Retrofit.Builder()
    .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
    .baseUrl("http://18.191.40.41:8081/")
    .client(okHttpClient)
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .build()

public val sendImageApi = retrofit.create(ApiService::class.java)

API服务代码:

@POST("test/")
@FormUrlEncoded
@Headers("Content-Type: application/x-www-form-urlencoded")
fun sendImage(@Field("inputImage") inputImage: String): Call<ImageResponse>;

通过 API 发送图像的代码:

        val stream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream)
        val image = stream.toByteArray()
        var response = sendImageApi.sendImage(Base64.encodeToString(image,0))
        response.enqueue(object :Callback<ImageResponse>{
            override fun onResponse(call: Call<ImageResponse>?, response: Response<ImageResponse>?) {
                Toast.makeText(activity,response?.body()?.toString(),Toast.LENGTH_SHORT).show()
                revertBtn.visibility = View.GONE
                sendBtn.visibility = View.GONE
                openCamera.visibility = View.GONE
                val imageBytes = Base64.decode(response.toString(), 0)
                val image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
                imageView.setImageBitmap(image)
            }
            override fun onFailure(call: Call<ImageResponse>?, t: Throwable) {
                imageView.visibility=View.GONE
                Toast.makeText(activity, t.message, Toast.LENGTH_SHORT).show()
            }
        })

节点 JS 服务器代码:

    var http = require('http');
    scriptPath = './imps/test.py';
    var cors = require('cors')
    const fs = require('fs');
    const files = fs.readdirSync('./');
    var Pythonshell = require('python-shell');
    var express = require('express');
    var app = express();
    var port = 8081;
    app.use(cors())

    app.use(express.static('./'));
    app.set('view engine', 'ejs');
    var bodyParser = require('body-parser');
    app.use(bodyParser.json()); // support json encoded bodies
    app.use(bodyParser.urlencoded({ extended: true ,limit: '10mb'}));
    app.use(function(req,res,next){
        res.header("Access-Control-Allow-Origin","*");
        res.header("Access-Control-Allow-Headers","Origin,X-Requested-With,Content-Type,Accept");
        next();
    });

    app.post('/test', function(req, res) {
        console.log("request received")
        img=req.body.inputImage
        fs.writeFile("./testImg/inputImage.jpg",img ,'base64', function(err) {
            if(err) {
                return console.log(err);
            }
        });

        Pythonshell.PythonShell.run(scriptPath, {args:['inputImage.jpg']}, function (err, results) {
            if (err) throw err;
            console.log(" python file called")
            console.log(results)
            var img = new Buffer(fs.readFileSync('./imps/result.png')).toString('base64');


            res.send(img);
        });

        // start the server

    });

我想接收一个字符串或对象作为包含 base64 图像的响应。

标签: androidnode.jspython-3.xkotlin

解决方案


当对等方无法访问时,使用超时使呼叫失败。网络分区可能是由于客户端连接问题、服务器可用性问题或介于两者之间的任何原因造成的。OkHttp 支持连接、读取和写入超时。更多信息

如果您不指定客户端,Retrofit 将创建一个具有默认连接和读取超时的客户端。要设置自己的超时,您需要配置自己的客户端并将其提供给RestAdapter.Builder.

使用 Square 的OkHttp客户端。

private final OkHttpClient client;

  public ConfigureTimeouts() throws Exception {
    client = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(10, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .build();
  }

  public void run() throws Exception {
    Request request = new Request.Builder()
        .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
        .build();

    try (Response response = client.newCall(request).execute()) {
      System.out.println("Response completed: " + response);
    }
  }

带改造

导入你的 gradle

implementation 'com.squareup.okhttp3:okhttp:3.12.1'

并使用OkHttpClient

final OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .readTimeout(60, TimeUnit.SECONDS)
        .connectTimeout(60, TimeUnit.SECONDS)
        .build();

return new Retrofit.Builder()
    .baseUrl(BuildConfig.BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .client(okHttpClient)
    .build();

推荐阅读