آموزش ارسال و دانلود تصاویر در اندروید

سلام دوستان در این مقاله نحوه ارسال تصاویر در یک اپلیکیشن اندروید آموزش داده می شود. برای انجام این کار از کتابخانه Retrofit  استفاده خواهیم کرد . این کتابخانه به ما این امکان را می دهد چندین درخواست را به سرور ارسال کنیم و همچنین از آن برای آپلود کردن فایل ها از اپلیکیشن به سرور استفاده کنیم . خوب بریم سراغ آموزش و ساخت پروژه  . همچنین کد های سمت سرور این پروژه با PHP و پایگاه داده MySQL می باشد. با آموزش استفاده از کتابخانه Retrofit برای ارسال تصاویر در اپلیکیشن اندروید با ما همراه باشید .

 فهرست:

۱.ساختمان APIs

  •     ایجاد پایگاه داده MySQL
  •     ایجاد پروژه PHP
  •     تعریف ثابت
  •     اتصال به پایگاه داده
  •     دایرکتوری ارسال
  •     بررسی فایل ارسال و دانلود
  •     مدیریت فرمان API

۲. آموزش Upload فایل با Retrofit

  •      ایجاد یک پروژه جدید
  •      افزودن کتابخانه ها
  •      ایجاد کلاس مدل برای پاسخ
  •      ایجاد رابط API
  •      آپلود فایل
  •      ایجاد رابط کاربری
  •      بررسی مجوز خواندن ذخیره سازی
  •      انتخاب یک فایل
  •      گرفتن مسیر مطلق از Uri
  •      ارسال فایل

۳.بارگیری تصاویر برگشت

۴.بارگیری مجدد فایل کد منبع

 

ساخت APIs

در این اپلیکیشن قصد داریم فایلی را به سرور ارسال کنیم  . بنابراین در سمت سرور  باید فایل را بگیریم و آنرا روی سرور ذخیره کنیم . برای انجام این وظایف API ایجاد می کنیم. در اینجا از سرور XAMPP استفاده می کنیم . شما میتوانید از هر سرور دیگری استفاده کنید.

ایجاد پایگاه داده MySQL

اولین گام ایجاد پایگاه داده است و ما به یک پایگاه داده که در زیر نمایش داده شده نیاز داریم

آموزش استفاده از کتابخانه Retrofit

پایگاه داده

 می توانید از SQL زیر برای ایجاد پایگاه داده فوق استفاده کنید.

CREATE TABLE `images` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `description` varchar(1000) NOT NULL,
  `image` varchar(500) NOT NULL
);

ایجاد پروژه PHP

برای ایجاد پروژه php در اینجا از PHP Storm استفاده می کنیم .اما شما می توانید از notepad++, sublime و چیز دیگری استفاده کنید.

یک پروژه جدید با نام  ImageUploadApi  داخل پوشه  c:/xampp/htdocs   ) htdocs  ) ایجاد می کنیم.

تعریف ثابت ها

ابتدا یک فایل با نام Constants.php برای تعریف تمام ثابتهای مورد نیاز ایجاد می کنیم.

<?php
/**
 * Created by PhpStorm.
 * User: Belal
 * Date: 10/5/2017
 * Time: 11:31 AM
 */
 
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', 'password');
define('DB_NAME', 'simplifiedcoding');
 
define('UPLOAD_PATH', '/uploads/');

اتصال به پایگاه داده

حالا  می خواهیم به پایگاه داده مان متصل شویم . برای این منظور یک کلاس PHP به نام DbConnect.php ایجاد می کنیم و کدهای زیر را می نویسیم.

<?php
 
/**
 * Created by PhpStorm.
 * User: Belal
 * Date: 10/5/2017
 * Time: 11:31 AM
 */
class DbConnect
{
    private $con;
 
    public function connect()
    {
        require_once dirname(__FILE__) . '/Constants.php';
 
        $this->con = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
 
        if (mysqli_connect_errno()) {
            echo 'Failed to connect ' . mysqli_connect_error();
            return null;
        }
 
        return $this->con;
    }
}

پوشه آپلود

یک پوشه درون پروژه خود با نام uploadsایجاد کنید.

در این پوشه تمام تصاویر آپلود شده توسط کاربر را ذخیره خواهیم کرد.

ارسال تصویر در اندروید

دوره آموزش اندروید

ذخیره و بازیابی فایل آپلود و دانلود

حالا ما یک کلاس دیگر با نام FileHandler.php برای ذخیره و بازیابی تصاویر ایجاد می کنیم

<?php
class FileHandler
{
 
    private $con;
 
    public function __construct()
    {
        require_once dirname(__FILE__) . '/DbConnect.php';
 
        $db = new DbConnect();
        $this->con = $db->connect();
    }
 
 
    public function saveFile($file, $extension, $desc)
    {
        $name = round(microtime(true) * 1000) . '.' . $extension;
        $filedest = dirname(__FILE__) . UPLOAD_PATH . $name;
        move_uploaded_file($file, $filedest);
 
        $url = $server_ip = gethostbyname(gethostname());
 
        $stmt = $this->con->prepare("INSERT INTO images (description, url) VALUES (?, ?)");
        $stmt->bind_param("ss", $desc, $name);
        if ($stmt->execute())
            return true;
        return false;
    }
 
    public function getAllFiles()
    {
        $stmt = $this->con->prepare("SELECT id, description, url FROM images ORDER BY id DESC");
        $stmt->execute();
        $stmt->bind_result($id, $desc, $url);
 
        $images = array();
 
        while ($stmt->fetch()) {
 
            $temp = array();
            $absurl = 'http://' . gethostbyname(gethostname()) . '/ImageUploadApi' . UPLOAD_PATH . $url;
            $temp['id'] = $id;
            $temp['desc'] = $desc;
            $temp['url'] = $absurl;
            array_push($images, $temp);
        }
 
        return $images;
    }
 
}

API مدیریت فرمانها

برای اینکار یک فایل PHP با نام Api.php ایجاد کرده و  تمامی فرمانهای API را کنترل خواهیم کرد.

<?php
require_once dirname(__FILE__) . '/FileHandler.php';
 
$response = array();
 
if (isset($_GET['apicall'])) {
    switch ($_GET['apicall']) {
        case 'upload':
 
            if (isset($_POST['desc']) && strlen($_POST['desc']) > 0 && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
                $upload = new FileHandler();
 
                $file = $_FILES['image']['tmp_name'];
 
                $desc = $_POST['desc'];
 
                if ($upload->saveFile($file, getFileExtension($_FILES['image']['name']), $desc)) {
                    $response['error'] = false;
                    $response['message'] = 'File Uploaded Successfullly';
                }
 
            } else {
                $response['error'] = true;
                $response['message'] = 'Required parameters are not available';
            }
 
            break;
 
        case 'getallimages':
 
            $upload = new FileHandler();
            $response['error'] = false;
            $response['images'] = $upload->getAllFiles();
 
            break;
    }
}
 
echo json_encode($response);
 
function getFileExtension($file)
{
    $path_parts = pathinfo($file);
    return $path_parts['extension'];
}

اکنون APIمان را تست می کنیم و برای اینکار می توانیم از REST Client استفاده کنیم.در اینجا ازPOSTMAN استفاده شده است.

آپلود تصویر در اندرویدتست API

API خوب کار می کند.حالا به بخش اندروید برویم.

آموزش آپلود فایل با کتابخانه Retrofit 

قسمت اصلی از اینجا شروع می شود.گام اول همیشه ایجاد یک پروژه جدید اندروید می باشد.

ایجاد یک پروژه جدید

یک پروژه جدید با نام RetrofitFileUpload ایجاد می کنیم.

زمانی که پروژه به طور کامل بارگذاری شد Retrofitو GSON را به آن اضافه می کنیم.

افزودن کتابخانه ها

داخل فایل build.gradle برنامه شوید و خطوط داده شده زیر را در بلوک dependencies وارد نمایید.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
 
    //these two lines are added
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
 
    testCompile 'junit:junit:4.12'
}

اکنون پروژه خود را هماهنگ (sync)  کنید

ایجاد کلاس مدل برای پاسخ

پاسخی که ما از سرور بعد از آپلود فایل دریافت می کنیم :

{
    "error": false,
    "message": "File Uploaded Successfullly"
}

برای خواندن پاسخ با لا از سرور یک کلاس مدل ایجاد خواهیم کرد.یک کلاس با نام MyResponse.java ایجاد کرده و کدهای زیر را می نویسیم.

package net.simplifiedlearning.retrofitfileupload;
public class MyResponse {
    boolean error;
    String message;
}

ایجاد رابط API

حالا به یک رابط برای تعریف همه فرمانهای API نیاز داریم.پس یک رابط با نام Api.java ایجاد کرده و کدهای زیر را می نویسیم.

package net.simplifiedlearning.retrofitfileupload;
 
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
public interface Api {
 
    //the base URL for our API
    //make sure you are not using localhost
    //find the ip usinc ipconfig command 
    String BASE_URL = "http://192.168.43.124/ImageUploadApi/";
 
    //this is our multipart request
    //we have two parameters on is name and other one is description
    @Multipart
    @POST("Api.php?apicall=upload")
    Call<MyResponse> uploadImage(@Part("image\"; filename=\"myfile.jpg\" ") RequestBody file, @Part("desc") RequestBody desc);
 
}

آپلود کردن فایل

   ایجاد رابط کاربری

برای ارسال  وگرفتن یک فایل ما به یک فایل انتخابگر نیاز داریم . بنابراین یک دکمه ایجاد می کنیم وبا ضربه زدن بر این دکمه اکتیویتی فایل انتخابگر را باز می کنیم.

یک دکمه درون activity_main.xml.ایجاد کنید.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="net.simplifiedlearning.retrofitfileupload.MainActivity">
 
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Upload Image" />
 
 
</RelativeLayout>

بررسی خواندن مجوز ذخیره سازی

در صورتیکه اپلیکیشن از ورژن بالاتر Lollipop اجرا شود پیغام مجوز دسترسی از ما درخواست خواهد شد اما همچنین باید مجوز مورد نیاز را در فایل manifest نیز وارد کنیم . مجوزی که اینجا لازم است مربوط به خواندن می باشد تا از آن برای آپلود تصاویر استفاده کنیم . ایتدا ما باید بتوانیم از مکان ذخیره سازی تصاویر فایل ها را بخوانیم و سپس فایل را آپلود کنیم .

پس فایل AndroidManifest.xml را باز کنید و مجوز خواندن را تعریف کنید.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.simplifiedlearning.retrofitfileupload">
 
    <!-- read and internet permission --> 
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>

مجوز اینترنت را به این صورت تعریف کردیم زیرا به آن نیاز داریم.اما چون نیازی به مجوز اینترنت در زمان اجرا نداریم.پس در onCreate() کد زیر را اضافه می کنیم.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                    Uri.parse("package:" + getPackageName()));
            finish();
            startActivity(intent);
            return;
        }

اگر برنامه مجوز خواندن از ذخیره ساز را نداشته باشد کد بالا برنامه را متوقف می کند و صفحه تنظیمات را باز می کند.

انتخاب یک فایل

ما کدهای زیر را در رویداد کلیک دکمه اضافه میکنیم برای اینکه فایل انتخابگر را باز کنیم.

Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
 startActivityForResult(i, 100);

هم اکنون باید نتیجه این گزینه فایل انتخابگر را پیگیری کنیم. برای انجام اینکار باید متد () onActivityResultرا Override کنیم.

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 100 && resultCode == RESULT_OK && data != null) {
            //the image URI
            Uri selectedImage = data.getData();
            
        }
    }

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

گرفتن مسیر واقعی از Uri

برای گرفتن مسیر واقعی از متد زیر استفاده میکنیم.

/*
    * This method is fetching the absolute path of the image file
    * if you want to upload other kind of files like .pdf, .docx
    * you need to make changes on this method only
    * Rest part will be the same
    * */
    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        CursorLoader loader = new CursorLoader(this, contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }

آپلود فایل

حالا برای آپلود کردن فایل  متد  ()upLoadFile را ایجاد می کنیم.

 private void uploadFile(Uri fileUri, String desc) {
        
        //creating a file
        File file = new File(getRealPathFromURI(fileUri));
 
        //creating request body for file
        RequestBody requestFile = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
        RequestBody descBody = RequestBody.create(MediaType.parse("text/plain"), desc);
 
        //The gson builder
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();
 
 
        //creating retrofit object
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Api.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        
        //creating our api 
        Api api = retrofit.create(Api.class);
 
        //creating a call and calling the upload image method 
        Call<MyResponse> call = api.uploadImage(requestFile, descBody);
 
        //finally performing the call 
        call.enqueue(new Callback<MyResponse>() {
            @Override
            public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
                if (!response.body().error) {
                    Toast.makeText(getApplicationContext(), "File Uploaded Successfully...", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Some error occurred...", Toast.LENGTH_LONG).show();
                }
            }
 
            @Override
            public void onFailure(Call<MyResponse> call, Throwable t) {
                Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }

تمام کدهای MainActivity.java به شرح ذیل است :

package net.simplifiedlearning.retrofitfileupload;
 
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.CursorLoader;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
 
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
 
import java.io.File;
import java.io.IOException;
 
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        //checking the permission
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(this,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                    Uri.parse("package:" + getPackageName()));
            finish();
            startActivity(intent);
            return;
        }
 
        //adding click listener to button
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //opening file chooser
                Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(i, 100);
            }
        });
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 100 && resultCode == RESULT_OK && data != null) {
            //the image URI
            Uri selectedImage = data.getData();
 
            //calling the upload file method after choosing the file 
            uploadFile(selectedImage, "My Image");
        }
    }
 
    private void uploadFile(Uri fileUri, String desc) {
 
        //creating a file
        File file = new File(getRealPathFromURI(fileUri));
 
        //creating request body for file
        RequestBody requestFile = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
        RequestBody descBody = RequestBody.create(MediaType.parse("text/plain"), desc);
 
        //The gson builder
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();
 
 
        //creating retrofit object
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Api.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
 
        //creating our api
        Api api = retrofit.create(Api.class);
 
        //creating a call and calling the upload image method
        Call<MyResponse> call = api.uploadImage(requestFile, descBody);
 
        //finally performing the call
        call.enqueue(new Callback<MyResponse>() {
            @Override
            public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
                if (!response.body().error) {
                    Toast.makeText(getApplicationContext(), "File Uploaded Successfully...", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(getApplicationContext(), "Some error occurred...", Toast.LENGTH_LONG).show();
                }
            }
 
            @Override
            public void onFailure(Call<MyResponse> call, Throwable t) {
                Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }
 
    /*
    * This method is fetching the absolute path of the image file
    * if you want to upload other kind of files like .pdf, .docx
    * you need to make changes on this method only
    * Rest part will be the same
    * */
    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        CursorLoader loader = new CursorLoader(this, contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }
}

حالا برنامه خود را اجرا کرده و آن را امتحان کنید  .

 

دوره آموزش اندروید

 

 

 

ورکشاپ رایگان دوره های تخصصی برنامه نویسی

شما این فرصت را دارید، با تکمیل فرم زیر، قبل از انتخاب دوره آموزشی مناسب خود، در ورکشاپ رایگان دوره های تخصصی برنامه نویسی شرکت کنید

درباره‌ی دولت آبادی

همچنین ببینید

آموزش اندروید

گزارش دوره آموزش اندروید – جلسه هفتم

در جلسه هفتم از دوره آموزش اندروید مهندس آذرنیوا مدرس دوره به آموزش ساخت اپلیکیشن تعاملی …

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *