PDA

View Full Version : ارسال تصویر به وب سرویس از طریق Volley



BeginnerProgrammer
یک شنبه 09 دی 1397, 12:29 عصر
سلام دوستان ، من یک فرم ارزشیابی دارم که برای 5تا از سوالات به دلخواه کاربر میشه عکس گرفت . بعد از تکمیل فرم ارزشیابی باید نتایج به وب سرویس ارسال بشه (همراه با عکسها ). برای همین من JSONObject از پاسخ کاربر میسازم که به این صورته :


{"evaluation":{"UserID":1,"EvaluationDate":"2018\/29\/12","EvaluationDetailsList":
[{"QuestionID":1,"Description":null,"Image":null,"PercentScore":0,"QuestionResponseID":3},
"QuestionID":2,"Description":null,"Image":null,"PercentScore":0,"QuestionResponseID":3},
"QuestionID":3,"Description":null,"Image":null,"PercentScore":0,"QuestionResponseID":3},
{"QuestionID":4,"Description":null,"Image":"B@927f5e6","PercentScore":0,"QuestionResponseID":3}]}}




و با کد زیر هم به وسرویس وصل میشم:


public void sendEvalResult(final JSONObject jsonObject, final ResultCallBack resultCallBack){
JSONObject finalObject=new JSONObject();
try {
finalObject.put("evaluation",jsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest req=new JsonObjectRequest(Request.Method.POST, Post_Evaluation_Result, finalObject,new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
resultCallBack.onGetResult(null);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
resultCallBack.onFailedGet();
}
}){
@Override
public String getBodyContentType() {
return "application/json;";
}
};


AppSingleton.getInstance(context).addToRequestQueu e(req,"PostResult");}


متغیر finalObject همون آبجکتیه که باید به وب سرویس ارسال بشه. وقتی این آبجکت عکسی نداشته باشه بخوبی کار میکنه ولی وقتی عکسی بهش اضافه میکنم خطا میده.
تا جایی که سرچ کردم به این نتیجه رسیدم که باید از MultiPartRequest استفاده کنم. ولی نمیدونم چطور میتونم از این رکوست برای درخواستی به این شکل استفاده کنم. ممنون میشم راهنمایی کنید.

farhad_shiri_ex
یک شنبه 09 دی 1397, 13:07 عصر
سلام دوستان ، من یک فرم ارزشیابی دارم که برای 5تا از سوالات به دلخواه کاربر میشه عکس گرفت . بعد از تکمیل فرم ارزشیابی باید نتایج به وب سرویس ارسال بشه (همراه با عکسها ). برای همین من JSONObject از پاسخ کاربر میسازم که به این صورته :


{"evaluation":{"UserID":1,"EvaluationDate":"2018\/29\/12","EvaluationDetailsList":
[{"QuestionID":1,"Description":null,"Image":null,"PercentScore":0,"QuestionResponseID":3},
"QuestionID":2,"Description":null,"Image":null,"PercentScore":0,"QuestionResponseID":3},
"QuestionID":3,"Description":null,"Image":null,"PercentScore":0,"QuestionResponseID":3},
{"QuestionID":4,"Description":null,"Image":"B@927f5e6","PercentScore":0,"QuestionResponseID":3}]}}




و با کد زیر هم به وسرویس وصل میشم:


public void sendEvalResult(final JSONObject jsonObject, final ResultCallBack resultCallBack){
JSONObject finalObject=new JSONObject();
try {
finalObject.put("evaluation",jsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest req=new JsonObjectRequest(Request.Method.POST, Post_Evaluation_Result, finalObject,new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
resultCallBack.onGetResult(null);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
resultCallBack.onFailedGet();
}
}){
@Override
public String getBodyContentType() {
return "application/json;";
}
};


AppSingleton.getInstance(context).addToRequestQueu e(req,"PostResult");}


متغیر finalObject همون آبجکتیه که باید به وب سرویس ارسال بشه. وقتی این آبجکت عکسی نداشته باشه بخوبی کار میکنه ولی وقتی عکسی بهش اضافه میکنم خطا میده.
تا جایی که سرچ کردم به این نتیجه رسیدم که باید از MultiPartRequest استفاده کنم. ولی نمیدونم چطور میتونم از این رکوست برای درخواستی به این شکل استفاده کنم. ممنون میشم راهنمایی کنید.

بهتره پیغام خطایی که میده را اینجا بذارید!
اگر حجم تصویر زیاد هست بهتره که تصاویر را جداگانه ارسال کنید وداخل رشته های Json ذخیره نکنید. احتمالا هم پیغام خطاتون برای همینه هست !
برای ارسال تصویر هم از picasso ویا از Volly.ImageRequest استفاده کنید البته کتابخانه picasso خیلی بهتر وقوی تر هست.

BeginnerProgrammer
یک شنبه 09 دی 1397, 13:34 عصر
بهتره پیغام خطایی که میده را اینجا بذارید!
اگر حجم تصویر زیاد هست بهتره که تصاویر را جداگانه ارسال کنید وداخل رشته های Json ذخیره نکنید. احتمالا هم پیغام خطاتون برای همینه هست !
برای ارسال تصویر هم از picasa ویا از Volly.ImageRequest استفاده کنید البته کتابخانه picasa خیلی بهتر وقوی تر هست.

متن پیغام اینه

'There was an error deserializing the object of type EQServices.Evaluation. End element 'Image' from namespace '' expected. Found text '[B@ef2e2bb'.'.


اگه بخوام از picasa استفاده کنم باید عکسها رو جدا بفرستم؟ با Volley.ImageRequest میشه کلا JSONObject رو فرستاد؟

farhad_shiri_ex
سه شنبه 11 دی 1397, 08:40 صبح
متن پیغام اینه

'There was an error deserializing the object of type EQServices.Evaluation. End element 'Image' from namespace '' expected. Found text '[B@ef2e2bb'.'.


اگه بخوام از picasso استفاده کنم باید عکسها رو جدا بفرستم؟ با Volley.ImageRequest میشه کلا JSONObject رو فرستاد؟

دقیقا پیغام خطایی گه دارید مبنی بر سریال کردن اشیا بزرگ هست که در اینجا JsonObject قصد داره که یک Image را دی سریال کنه که موفق نمیشه !
همانطور که عرض کردم اصلا نیازی نیست که داخل یک آبجکت Json تصاویر را ارسال کنید.
Volley.ImageRequest با این کلاس می تونید تصاویر را به byte به سرور ارسال کنید و در سرور هم بایت ها را دریافت کنید وداخل یک فایل بنویسید(البته اگر برنامه ای که دارید خیلی با تصویر کار داره اصلا پیشنهاد نمیکنم از این روش استفاده کنید.)
با کتابخانه picasso می تونید به راحتی هر چقدر تصویر دارید را باهم ویا تک تک به سرور ارسال کنید و سمت سرور هم دریافت کنید تو گوگل نحوه استفاده از این کتابخانه خیلی زیاد هست.

BeginnerProgrammer
سه شنبه 11 دی 1397, 09:43 صبح
من برای picasa سرچ کردم اصلا چیزی پیدا نشد، منظورتون همون picasso؟ بازهم من مطلبی در مورد اینکه بشه با این کتابخونه تصویر پست کرد پیدا نکردم.

farhad_shiri_ex
سه شنبه 11 دی 1397, 11:04 صبح
من برای picasa سرچ کردم اصلا چیزی پیدا نشد، منظورتون همون picasso؟ بازهم من مطلبی در مورد اینکه بشه با این کتابخونه تصویر پست کرد پیدا نکردم.

اینجا را نگاه کردید!

http://square.github.io/picasso/

البته از کلاس های زیر هم می تونی استفاده کنی!

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
//import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity ;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;


public class MainActivity extends Activity {

Button btpic, btnup;
private Uri fileUri;
String picturePath;
Uri selectedImage;
Bitmap photo;
String ba1;
public static String URL = "Paste your URL here";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btpic = (Button) findViewById(R.id.cpic);
btpic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clickpic();
}
});

btnup = (Button) findViewById(R.id.up);
btnup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
upload();
}
});
}

private void upload() {
// Image location URL
Log.e("path", "----------------" + picturePath);

// Image
Bitmap bm = BitmapFactory.decodeFile(picturePath);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte[] ba = bao.toByteArray();
//ba1 = Base64.encodeBytes(ba);

Log.e("base64", "-----" + ba1);

// Upload image to server
new uploadToServer().execute();

}

private void clickpic() {
// Check Camera
if (getApplicationContext().getPackageManager().hasSy stemFeature(
PackageManager.FEATURE_CAMERA)) {
// Open default camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

// start the image capture Intent
startActivityForResult(intent, 100);

} else {
Toast.makeText(getApplication(), "Camera not supported", Toast.LENGTH_LONG).show();
}
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100 && resultCode == RESULT_OK) {

selectedImage = data.getData();
photo = (Bitmap) data.getExtras().get("data");

// Cursor to get image uri to display

String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
picturePath = cursor.getString(columnIndex);
cursor.close();

Bitmap photo = (Bitmap) data.getExtras().get("data");
ImageView imageView = (ImageView) findViewById(R.id.Imageprev);
imageView.setImageBitmap(photo);
}
}

public class uploadToServer extends AsyncTask<Void, Void, String> {

private ProgressDialog pd = new ProgressDialog(MainActivity.this);
protected void onPreExecute() {
super.onPreExecute();
pd.setMessage("Wait image uploading!");
pd.show();
}

@Override
protected String doInBackground(Void... params) {

ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("base64", ba1));
nameValuePairs.add(new BasicNameValuePair("ImageName", System.currentTimeMillis() + ".jpg"));
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(URL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
String st = EntityUtils.toString(response.getEntity());
Log.v("log_tag", "In the try Loop" + st);

} catch (Exception e) {
Log.v("log_tag", "Error in http connection " + e.toString());
}
return "Success";

}

protected void onPostExecute(String result) {
super.onPostExecute(result);
pd.hide();
pd.dismiss();
}
}
}

برای سرور هم اگر از php استفاده کردی!...


<?php
error_reporting(E_ALL);
if(isset($_POST['ImageName'])){
$imgname = $_POST['ImageName'];
$imsrc = base64_decode($_POST['base64']);
$fp = fopen($imgname, 'w');
fwrite($fp, $imsrc);
if(fclose($fp)){
echo "Image uploaded";
}else{
echo "Error uploading image";
}
}
?>

BeginnerProgrammer
سه شنبه 11 دی 1397, 11:11 صبح
ممنون از راهنماییتون :لبخندساده::لبخندساده::لبخن ساده:
ظاهرن دکمه تشکر کردنو برداشتن من خیلی وقتا اینجا نیومدم :))))
ولی به نظر گزینه multipart مربوط به کتابخانه retrofit هم گزینه مناسبیه.
base64 حجم زیادی رو اشغال نمیکنه؟

farhad_shiri_ex
سه شنبه 11 دی 1397, 11:31 صبح
ولی به نظر گزینه multipart مربوط به کتابخانه retrofit هم گزینه مناسبیه.


بله retrofit هم فوق العادست بستگی به پیچیدگی برنامه و سطح کاربری داره استفاده از این کتابخانه ها!


base64 حجم زیادی رو اشغال نمیکنه؟

منظورتون از اشغال حجم چی؟ در مثالی که قرار دادم شما باید یک تصویر را تبدیل به بایت استریم کنید که این کار هم به دوروش قابل استفاده است بدون کد کردن با استفاده از کلاس ByteArrayOutputStream و یک راه هم استفاده از encoder base64 هست که البته همانطور که مبینید اون قسمت کامنت شده!
و بعد هم که دریافت بایت استریم ها و ذخیره در یک فایل.
خوب باالطبع برای اینکه روشهای امنیت تصاویر تون را فراهم کنید باید با استفاده از روش های رمزنگاری متوسل بشید که یکیش همین base64 هست البته امنیت خیلی قوی نداره ولی اگر با یک salt و یک کلید خاص جمع کنید و سمت سرور هم می تونید از decoder مربوطه استفاده کنید تا حداقل از sniffing پورت و ای پی وب سرویس هاتون یکمی جلوگیری کنید. البته روشهایی قوی تری برای تنضمین امنیت وجود داره این فقط یک راه کوچیک هست...


ممنون از راهنماییتون :لبخندساده::لبخندساده::لبخن ساده:
ظاهرن دکمه تشکر کردنو برداشتن من خیلی وقتا اینجا نیومدم :))))

خواهش میکنم !
دکمه تشکر هم رفته که بیاد منتهی هنوز تصمیم نگرفته که بیاد. فکر کنم دیگه به عمر ما قد نده!