【问题标题】:Upload byte[] image to server via multipart通过 multipart 将 byte[] 图像上传到服务器
【发布时间】:2018-05-25 07:17:55
【问题描述】:

我正在开发 Android 上的图像上传功能,我正在使用这两个库: https://github.com/natario1/CameraView

https://github.com/gotev/android-upload-service

所以,根据 CameraView 库,我可以得到这样的照片:

mCameraView.addCameraListener(new CameraListener() {
      @Override
      public void onPictureTaken(byte[] jpeg) {
          super.onPictureTaken(jpeg);
      }
});

所以我有我的图片作为字节数组。这里的问题是如何通过多部分将其上传到我的服务器?我的后端已准备好接受文件。 所以我相信我必须将我的 byte[] 转换为文件?

编辑 1:抱歉,这个问题很不清楚,问题应该缩小到“如何将字节 [] 写入文件。

【问题讨论】:

  • 只需使用 HttpUrlConnection 将字节发送到服务器。您不需要先创建文件。

标签: android camera-view


【解决方案1】:

首先,您必须将字节存储到文件中。存储图像后转换为 Multipart

File file = new File(fileUri);
            RequestBody reqFile = RequestBody.create(MediaType.parse("image*//*"), file);
            MultipartBody.Part body =  MultipartBody.Part.createFormData(AppConstants.IMAGE, file.getName(), reqFile);


private File saveImage(byte[] bytes, int rotate) {
        try {
            Bitmap bitmap = decodeSampledBitmapFromResource(bytes, bytes.length, 800, 600, rotate);

            return createFile(bitmap);
        } catch (Exception e) {
            Log.e("Picture", "Exception in photoCallback", e);
        }
        return null;
    }

    public Bitmap decodeSampledBitmapFromResource(byte[] bytes, int length, int reqWidth,
                                                  int reqHeight, int rotate) {

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(bytes, 0, length, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds = false;
        Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, length, options);
        Bitmap rotatedBitmap = null;
        if (isFrontfaceing) {
            if (rotate == 90 || rotate == 270) {
                rotatedBitmap = rotateImage(bm, -rotate);
            } else {
                rotatedBitmap = rotateImage(bm, rotate);
            }
        } else {
            rotatedBitmap = rotateImage(bm, rotate);
        }
        rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, reqWidth, reqHeight, true);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        return rotatedBitmap;
    }

    public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth,
                                     int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    || (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }


 public File createFile(Bitmap bitmap) {
    File photo =
            new File(getWorkingDirectory().getAbsolutePath()+"yourFileName" + ".jpg");
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(photo.getPath());
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
    return photo;
}

【讨论】:

  • 为什么要先把那个jpg转换成位图?并调整大小?并旋转?很多不需要的代码。您应该直接将这些字节写入文件而不使用中间位图。
  • 是的...这就是我用来调整图像大小的。您可以直接将字节保存到文件中
  • @himangi,感谢您的回答,它帮助我解决了我的问题。基本上我认为我的问题的范围是非常错误的,我需要的只是学习如何将 byte[] 写入文件,这很简单)
【解决方案2】:

基本上我们需要的只是将我们的 byte[] 写入文件。首先,我为此创建占位符文件。这是从谷歌官方文档 (https://developer.android.com/training/camera/photobasics#TaskPhotoView) 中截取的代码

    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,
                ".jpg",
                storageDir
        );
        
        return image;
    }

然后我将我的 byte[] 写入该文件。

    try {
       File photoFile = createImageFile();
       FileOutputStream fos = new FileOutputStream(photoFile.getPath());
       fos.write(jpeg);
       // then call uploadImage method and pass aboslutePath of my file
       uploadImage(photoFile.getAbsolutePath());
       } catch (IOException e) {}

uploadImage方法根据android-upload-service处理上传:https://github.com/gotev/android-upload-service

【讨论】:

  • First of all I create placeholder file for that.。不好。不要使用 File.createTempFile()。该文件将由新的 FileOutputStream 创建。你只需要一个文件名/路径。
  • @greenapps 实际上不需要写入任何临时文件 - 你只需要传递一个自定义的 RequestBody 类接受你的字节数组并覆盖 contentTypewriteTo 方法
  • @pskink 请告诉 OP。他可以使用它。您也可以将其发布为答案。
  • @greenapps OP 已经说过:"thanks for answer, it helped me a lot to solve my problem. Basically I think the scope of my question is quite wrong, what I needed is just to learn how to write byte[] to file, which is fairly simple)" 所以我不认为我可以改变他的想法(但我认为如果你将来需要做这样的事情我可以改变你)
  • @pskink 非常有趣。您可能没有看到我的第一条评论:Just use HttpUrlConnection to post the bytes to the server. You dont need to create a file first。确实...我也可以将其发布为答案 ;-)。
猜你喜欢
  • 1970-01-01
  • 2017-05-21
  • 2021-01-20
  • 2019-03-25
  • 2014-11-25
  • 2015-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多