通过摄像头拍照并以bytearray的forms发送到服务器

我正在开发一个Andorid应用程序,我想让用户拍照,然后保存它我将它发送到服务器。 现在,我将图片作为字节数组发送到服务器。 当我尝试将字节数组作为PNG文件保存到文件中,然后尝试打开文件时,图像查看器会抱怨PNG有错误并且无法显示。 PNG文件大小为122Kb。

当我尝试使用Scalr库来调整图像大小时,它表示图像源不能为空。 直接保存字节数会导致PNG损坏。 我应该如何将文件正确转换并发送到服务器,因此没有错误。 这是我正在使用并发送它的相机代码。

public class AddPhotoForUser extends DrawerLoader { private static final int CAMERA_PIC_REQUEST = 22; Button BtnSelectImage; private ImageView ImgPhoto; private static volatile Bitmap photo; private static volatile ByteArrayOutputStream stream = new ByteArrayOutputStream(); final PersonServiceImpl personService = new PersonServiceImpl(); private String[] navMenuTitles; private TypedArray navMenuIcons; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.upload_user_photo); navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items); navMenuIcons = getResources() .obtainTypedArray(R.array.nav_drawer_icons); set(navMenuTitles, navMenuIcons); Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton); uploadImageButton.setVisibility(View.INVISIBLE); ImgPhoto = (ImageView) findViewById(R.id.userPhotoImageView); BtnSelectImage = (Button) findViewById(R.id.userPhotoButtonSelect); BtnSelectImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST); } catch (Exception e) { Toast.makeText(getApplicationContext(), "Couldn't load photo", Toast.LENGTH_LONG).show(); } } }); uploadImageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!(v == null)) { uploadImage(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } Intent intent = new Intent(AddPhotoForUser.this, RestaurantList.class); startActivity(intent); finish(); } } }); } @Override public void onBackPressed() { Intent intent = new Intent(AddPhotoForUser.this, Login.class); startActivity(intent); finish(); } @Override public void onActivityResult(final int requestCode, int resultCode, Intent data) { try { switch (requestCode) { case CAMERA_PIC_REQUEST: if (resultCode == RESULT_OK) { try { photo = (Bitmap) data.getExtras().get("data"); if (!(photo == null)) { ImgPhoto.setImageBitmap(photo); Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton); uploadImageButton.setVisibility(View.VISIBLE); } } catch (Exception e) { Toast.makeText(this, "Couldn't load photo", Toast.LENGTH_LONG).show(); } } break; default: break; } } catch (Exception e) { e.printStackTrace(); } } private void uploadImage() { if (!(photo == null)) { photo.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); personService.addUserProfilePhoto(byteArray); } } } 

以下是将映像保存到磁盘的服务器端代码:

  @Override public Boolean updateProfilePhoto(byte[] photo) { Person person = getCurrentlyAuthenticatedPerson(); try{ InputStream in = new ByteArrayInputStream(photo); BufferedImage image = ImageIO.read(in); image = Scalr.resize(image, Scalr.Method.QUALITY, 100, 100); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "png", baos); baos.flush(); File file = new File(userImagePath); if (file.exists() && file.isDirectory()) { OutputStream outputStream = new FileOutputStream(new File(userImagePath + person.getUserId()+".png")); outputStream.write(baos.toByteArray()); outputStream.close(); } else { File file1 = new File(userImagePath+person.getUserId()+".png"); if (file1.exists()) { try { OutputStream outputStream = new FileOutputStream(file1); outputStream.write(baos.toByteArray()); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } else { boolean result = file1.createNewFile(); System.out.println("Result of file1 creation is "+result); OutputStream outputStream = new FileOutputStream(file1); outputStream.write(baos.toByteArray()); outputStream.close(); } } return true; }catch (Exception e){ e.printStackTrace(); return false; } } 

如果我不使用Scalr库,则没有错误,但它是一个损坏的文件。 这是Scalr错误日志:

 java.lang.IllegalArgumentException: src cannot be null at org.imgscalr.Scalr.resize(Scalr.java:1564) at org.imgscalr.Scalr.resize(Scalr.java:1415) at com.journaldev.spring.service.PersonServiceImpl.updateProfilePhoto(PersonServiceImpl.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy51.updateProfilePhoto(Unknown Source) at com.journaldev.spring.Controller.PersonController.addProfilePhotoForUser(PersonController.java:100) 

你能帮忙的话,我会很高兴。 非常感谢。 🙂

更新的代码

 public class AddPhotoForUser extends DrawerLoader { Button BtnSelectImage; private ImageView ImgPhoto; private static volatile ByteArrayOutputStream stream = new ByteArrayOutputStream(); final PersonServiceImpl personService = new PersonServiceImpl(); private String[] navMenuTitles; private TypedArray navMenuIcons; private static final int CAMERA_PHOTO = 111; private Uri imageToUploadUri; Bitmap reducedSizeBitmap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.upload_user_photo); navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items); navMenuIcons = getResources() .obtainTypedArray(R.array.nav_drawer_icons); set(navMenuTitles, navMenuIcons); Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton); uploadImageButton.setVisibility(View.INVISIBLE); ImgPhoto = (ImageView) findViewById(R.id.userPhotoImageView); BtnSelectImage = (Button) findViewById(R.id.userPhotoButtonSelect); BtnSelectImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { captureCameraImage(); } catch (Exception e) { Toast.makeText(getApplicationContext(), "Couldn't load photo", Toast.LENGTH_LONG).show(); } } }); uploadImageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!(v == null)) { uploadImage(); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } Intent intent = new Intent(AddPhotoForUser.this, RestaurantList.class); startActivity(intent); finish(); } } }); } private Bitmap getBitmap(String path) { Uri uri = Uri.fromFile(new File(path)); InputStream in = null; try { final int IMAGE_MAX_SIZE = 12000000; // 12MP in = getContentResolver().openInputStream(uri); // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, o); in.close(); int scale = 1; while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { scale++; } Log.d("", "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight); Bitmap b = null; in = getContentResolver().openInputStream(uri); if (scale > 1) { scale--; // scale to max possible inSampleSize that still yields an image // larger than target o = new BitmapFactory.Options(); o.inSampleSize = scale; b = BitmapFactory.decodeStream(in, null, o); // resize to desired dimensions int height = b.getHeight(); int width = b.getWidth(); Log.d("", "1th scale operation dimenions - width: " + width + ", height: " + height); double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height)); double x = (y / height) * width; Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x, (int) y, true); b.recycle(); b = scaledBitmap; System.gc(); } else { b = BitmapFactory.decodeStream(in); } in.close(); Log.d("", "bitmap size - width: " + b.getWidth() + ", height: " + b.getHeight()); return b; } catch (IOException e) { Log.e("", e.getMessage(), e); return null; } } private void captureCameraImage() { Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File f = new File(Environment.getExternalStorageDirectory(), "POST_IMAGE.jpg"); chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); imageToUploadUri = Uri.fromFile(f); startActivityForResult(chooserIntent, CAMERA_PHOTO); } @Override public void onBackPressed() { Intent intent = new Intent(AddPhotoForUser.this, Login.class); startActivity(intent); finish(); } @Override protected void onActivityResult(final int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAMERA_PHOTO && resultCode == Activity.RESULT_OK) { if(imageToUploadUri != null){ Uri selectedImage = imageToUploadUri; getContentResolver().notifyChange(selectedImage, null); reducedSizeBitmap = getBitmap(imageToUploadUri.getPath()); if(reducedSizeBitmap != null){ ImgPhoto.setImageBitmap(reducedSizeBitmap); Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton); uploadImageButton.setVisibility(View.VISIBLE); }else{ Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show(); } }else{ Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show(); } } } private void uploadImage() { if(!(reducedSizeBitmap == null)){ reducedSizeBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); this.personService.addUserProfilePhoto(byteArray); } } } 

上传的图片截图

如果你使用Bundle extras = data.getExtras(); 在你的onActivityResult()然后它将返回缩略图而不是实际图像。

这是我用于捕获和保存摄像机图像然后将其显示到ImageView 。 您可以根据自己的需要使用。

您必须将摄像机图像保存到特定位置,然后从该位置获取然后将其转换为字节数组。

这是用于打开捕获相机图像活动的方法。

 private static final int CAMERA_PHOTO = 111; private Uri imageToUploadUri; private void captureCameraImage() { Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File f = new File(Environment.getExternalStorageDirectory(), "POST_IMAGE.jpg"); chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f)); imageToUploadUri = Uri.fromFile(f); startActivityForResult(chooserIntent, CAMERA_PHOTO); } 

那么你的onActivityResult()方法应该是这样的。

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAMERA_PHOTO && resultCode == Activity.RESULT_OK) { if(imageToUploadUri != null){ Uri selectedImage = imageToUploadUri; getContentResolver().notifyChange(selectedImage, null); Bitmap reducedSizeBitmap = getBitmap(imageToUploadUri.getPath()); if(reducedSizeBitmap != null){ ImgPhoto.setImageBitmap(reducedSizeBitmap); Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton); uploadImageButton.setVisibility(View.VISIBLE); }else{ Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show(); } }else{ Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show(); } } } 

这是onActivityResult()使用的getBitmap()方法。 在获取相机捕获图像位图时,我已经完成了所有可能的性能改进。

 private Bitmap getBitmap(String path) { Uri uri = Uri.fromFile(new File(path)); InputStream in = null; try { final int IMAGE_MAX_SIZE = 1200000; // 1.2MP in = getContentResolver().openInputStream(uri); // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, o); in.close(); int scale = 1; while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { scale++; } Log.d("", "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight); Bitmap b = null; in = getContentResolver().openInputStream(uri); if (scale > 1) { scale--; // scale to max possible inSampleSize that still yields an image // larger than target o = new BitmapFactory.Options(); o.inSampleSize = scale; b = BitmapFactory.decodeStream(in, null, o); // resize to desired dimensions int height = b.getHeight(); int width = b.getWidth(); Log.d("", "1th scale operation dimenions - width: " + width + ", height: " + height); double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height)); double x = (y / height) * width; Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x, (int) y, true); b.recycle(); b = scaledBitmap; System.gc(); } else { b = BitmapFactory.decodeStream(in); } in.close(); Log.d("", "bitmap size - width: " + b.getWidth() + ", height: " + b.getHeight()); return b; } catch (IOException e) { Log.e("", e.getMessage(), e); return null; } } 

编辑:

这是将图像上传到服务器的方法。

 /** * Upload Image to server * * @param file image to be saved * @param compressorQuality quality of image * @return path of uploaded image in server */ private String uploadImage(Bitmap file, int compressorQuality) { String final_upload_filename = "demo_image.png"; String response = null; HttpURLConnection conn = null; try { String lineEnd = "\r\n"; String twoHyphens = "--"; String boundary = "---------------------------14737809831466499882746641449"; URL url = new URL("image_upload_url"); conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("ENCTYPE", "multipart/form-data"); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); conn.setRequestProperty("uploaded_file", final_upload_filename); DataOutputStream dos = new DataOutputStream(conn.getOutputStream()); dos.writeBytes(lineEnd + twoHyphens + boundary + lineEnd); dos.writeBytes("Content-Disposition: form-data; name=\"userfile\"; filename=\"" + final_upload_filename + "\"" + lineEnd); dos.writeBytes("Content-Type: application/octet-stream" + lineEnd); dos.writeBytes(lineEnd); file.compress(CompressFormat.PNG, compressorQuality, dos); dos.writeBytes(lineEnd); dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); dos.flush(); dos.close(); InputStream is = conn.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bytesRead; byte[] bytes = new byte[1024]; while ((bytesRead = is.read(bytes)) != -1) { baos.write(bytes, 0, bytesRead); } byte[] bytesReceived = baos.toByteArray(); baos.close(); is.close(); response = new String(bytesReceived); } catch (Exception e) { e.printStackTrace(); } finally { if (conn != null) { conn.disconnect(); } } return response; } 

您需要在后端服务器中创建上载脚本以将图像数据存储在特定文件夹中。

我希望它有所帮助!

首先,您需要创建一个文件并在其上保存图像,这是一个代码。

//在内部或外部存储中保存图像的方法

 private void storeImage(Bitmap image,String imageName) { File pictureFile = getOutputMediaFile(imageName); if (pictureFile == null) { Log.d(TAG,"Error creating media file, check storage permissions: ");// e.getMessage()); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); image.compress(Bitmap.CompressFormat.PNG, 90, fos); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } } 

//创建文件以保存图像的方法

 private File getOutputMediaFile(String imageName){ //create folder with name FoursquareAPI File mediaStorageDir = new File(Environment.getExternalStorageDirectory() + "/FoursquareAPI"); // Create the storage directory if it does not exist if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ return null; } } File mediaFile; String mImageName= imageName +".png"; mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName); return mediaFile; }