【问题标题】:How to POST a bitmap to a server using Retrofit/Android如何使用 Retrofit/Android 将位图发布到服务器
【发布时间】:2018-01-31 09:00:53
【问题描述】:

我正在尝试使用AndroidRetrofit 将位图发布到服务器。

目前我知道如何发布文件,但我更喜欢直接发送位图。

这是因为用户可以从他们的设备上选择任何图像。我想在它被发送到服务器之前调整它的大小以节省带宽,最好不必加载它,调整它的大小,将它作为文件保存到本地存储然后发布文件。

有人知道如何从Retrofit 发布位图吗?

【问题讨论】:

    标签: android retrofit


    【解决方案1】:
    Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
    byte[] byteArray = stream.toByteArray();
    

    您可以将位图转换为字节数组,然后将此字节数组发布到服务器后,您可以制作一个临时文件,例如

    File file = new File(this.getCacheDir(), filename);
    

    文件直接上传到服务器

    【讨论】:

      【解决方案2】:

      注意:在除 Main 之外的其他线程上进行此转换。 RxJava 可以帮助实现这一点,或者协程

      首先将您的位图转换为文件

      //create a file to write bitmap data
      File f = new File(context.getCacheDir(), filename);
      f.createNewFile();
      
      //Convert bitmap to byte array
      Bitmap bitmap = your bitmap;
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      bitmap.compress(CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
      byte[] bitmapdata = bos.toByteArray();
      
      //write the bytes in file
      FileOutputStream fos = null;
          try {
              fos = new FileOutputStream(f);
          } catch (FileNotFoundException e) {
              e.printStackTrace();
          }
          try {
              fos.write(bitmapdata);
              fos.flush();
              fos.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
      

      然后使用Multipart 创建一个请求以上传您的文件

      RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), f);
      MultipartBody.Part body = MultipartBody.Part.createFormData("upload", f.getName(), reqFile);
      

      您的服务调用应如下所示

      interface Service {
          @Multipart
          @POST("/yourEndPoint")
          Call<ResponseBody> postImage(@Part MultipartBody.Part image);
      }
      

      然后调用你的 api

      Service service = new Retrofit.Builder().baseUrl("yourBaseUrl").build().create(Service.class);
      Call<okhttp3.ResponseBody> req = service.postImage(body);
      req.enqueue(new Callback<ResponseBody>() {
          @Override
          public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { 
               // Do Something with response
          }
      
          @Override
          public void onFailure(Call<ResponseBody> call, Throwable t) {
              //failure message
              t.printStackTrace();
          }
      });
      

      【讨论】:

      • 从位图创建文件耗时太长.. 是否有可能使这个速度变快,或者我们必须在 asynctask 中执行此操作才能显示中间的加载程序??
      • 从位图创建文件是一个漫长的过程,需要一些内存。您应该使用 Asynctask 或 Thead。您需要从 MainThread 移动文件创建以避免阻塞 UI。是的,在这个过程中显示一个加载器。
      • 我做到了,每次都需要 25 到 30 秒......当我从 cam 捕捉时......
      • 这需要很多,我认为你做错了什么。你的文件有多大?
      • 所以在压缩时我使用 JPEG 而不是 PNG,然后它加快了处理速度.. 谢谢你..
      【解决方案3】:

      建议通过文件上传位图/图像。图像应保存在设备存储中,然后您应该多部分发送文件。但是如果您有要求不将位图/图像存储在存储中并直接通过 Retrofit 上传,那么您可以这样做。

      1. 获取 Bitmap 并将其转换为字节数组 (byte[])
      2. 在 Base64 中转换 byte[](Base64 将是单个字符串)
      3. 像普通字符串一样上传 Base64 字符串

      当您需要在应用程序或后端显示图像时。将base64转为字节,将字节转为Bitmap并显示Bitmap。

      将位图转换为字节[]

        public static byte[] bitmapToBytes(Bitmap photo) {
          ByteArrayOutputStream stream = new ByteArrayOutputStream();
          photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
          return stream.toByteArray();
        }
      

      将 byte[] 转换为 Base64 字符串

      public static String bytesToBase64(byte[] bytes) {
          final String base64 = Base64.encodeToString(bytes, 0);
          return base64;
      }
      

      将 Base64 字符串转换为字节[]

      public static byte[] base64ToBytes(String base64) {
          final byte[] bytes = Base64.decode(base64, 0);
          return bytes;
      }
      

      将字节[]转换为位图

      public static Bitmap bytesToBitmap(byte[] bytes) {
          final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
          return bitmap;
      }
      

      我见过有人上传这样的图片,但我个人更喜欢通过文件上传。

      【讨论】:

        猜你喜欢
        • 2014-05-10
        • 2016-09-29
        • 1970-01-01
        • 2021-03-18
        • 2015-07-27
        • 1970-01-01
        • 1970-01-01
        • 2017-01-14
        相关资源
        最近更新 更多