آپلود فایل در اندروید
یکی از مهترین مباحث برنامه نویسی بخصوص در حوزه برنامه نویسی سوکت و شبکه، مربوط به آپلود کردن فایل به سرور است .آپلود کردن بر اساس اهمیتی که برای برخی از برنامه ها همانند انتقال اطلاعات ، ذخیره سازی و … دارد ضرورت یادگیری و بکارگیری آن را اجتناب ناپذیر می کند و می توان به جرات گفت با یادگیری همین موضوع و بکارگیری صحیح آن می توان موفقیت های بسیاری را در تولید اپلیکیشن های حرفه ای بدست آورد. از این رو، بر آن شدیم که در این مقاله به آموزش این موضوع بپردازیم. طبق روال آموزشی سایت، ابتدا ساختار کلی و اصلی موضوع را آموزش می دهیم و سپس بر اساس آموزش ارائه شده مثالی ارائه می کنیم تا از این طریق بهتر و بیشتر به درک موضوع نائل شوید.
گام اول: تعریف لوکیشن فایل و نام فایل در دیوایس: در این مثال ابتدا آدرس دایرکتوری و سپس نام فایل بصورت string برای برنامه تعریف شده است
final String uploadFilePath = "/mnt/sdcard/";
final String uploadFileName = "imageupload.jpg";
گام دوم: تعریف URL: آدرس مورد نظر جهت آپلود عکس و همچنین فراخوانی کلاس URL بصورت زیر تعریف شده است:
upLoadServerUri = "http://psrd.ir/fixurl/upload.php"
URL url = new URL(upLoadServerUri);
گام سوم : فراخوانی کلاس FileInputStream برای خواندن ورایت کردن فایل(عکس) از منبع تعریف شده دیوایس:
FileInputStream fileInputStream = new FileInputStream(sourceFile);
گام چهارم: فراخوانی کلاس HttpURLConnection برای اتصال به URL:
conn = (HttpURLConnection) url.openConnection();
گام پنچم : اعمال تنظیمات مربوط به HttpURLConnection که URL مورد را باز نموده، قابلیت input و output کردن را فعال می کند ، امکان کپی کردن cahed را غیرفعال می کند ، متد ارسال را post قرار می دهد ، از مرورگر برای برای انتقال چندین فایل از یک ارتباط (connection) استفاده می کند. امکان ارسال متوالی و غیر منقطع فایل را اعمال می کند.
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
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", fileName);
گام ششم فراخوانی کلاس DataStream ها برای خواندن و نوشتن فایلآن توسط متد ()getOutputStream ، برای کانکشن تعریف شده،
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: " +
"form-data; name=\"uploaded_file\";filename=\"\" + fileName + \"\"" + lineEnd);
dos.writeBytes(lineEnd);
گام هفتم تعیین حجم بافر یا حافظه میانگر :
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
گام هشتم : خواندن و نوشتن فایل با فراخوانی کلاس fileInputStream، با حجم تعیین شده بافر ،
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
گام نهم : ارسال چندگانه از اطلاعات ضروری برای رایت فایل در سرور
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
گام دهم : گرفتن پاسخ از سرور به منظور تعیین موفقیت آمیز بودن عملیات که با responsive 200 مشخص می شود.
rverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
Log.i("uploadFile", "HTTP Response is : "
+ serverResponseMessage + ": " + serverResponseCode);
if(serverResponseCode == 200){
runOnUiThread(new Runnable() {
public void run() {
String msg = "File Upload Completed.\n\n See uploaded file here : \n\n"
+" http://www.psrd.ir/fixurl/uploads/"
+uploadFileName;
messageText.setText(msg);
Toast.makeText(UploadToServer.this,
"File Upload Complete.", Toast.LENGTH_SHORT).show();
}
});
}
گام یازدهم : بستن استریم های fileInputStream و DataOutputStream
fileInputStream.close();
dos.flush();
dos.close();
مثالی که در ذیل ارائه شده است نمونه ای از روش آپلود عکس به سرور است. برای این کار مقدمتاً، عکس مورد نظر خود را در sdcard گوشی در مسیر مشخصی قرار دهید و نام آن imageupload.jpg بگذارید. همچنین لازم است که به منظور آپلود در سرور، فایلی با پسوند php در مسیر مشخصی از سرور خود در l داخل پوشهpublic htm ایجاد کنید و آدرس آن را از سرور خود استخراج کرده و آن را در مرورگر خود امتحان کنید. در کنار فایل php، دایرکتوری یا پوشه ای با نامuploads ایجاد کنید چرا که قرار است فایل های آپلود شده در این دایرکتوری قرار گیرند. البته در مثالی که ارائه شده است این فایل در سرور هاست وب سایت قرار دارد و شما با استفاده از مثال ارائه شده قادر خواهید بود که عکس مورد نظر خود را آپلود کنید.
اگر در داخل برنامه اکلیپس یا اندروید استودیو قرار دارید پروژه جدیدی را ایجاد کنید
اکلیپس :File ⇒ New Android ⇒ Application Project
اندروید استودیو :File ⇒ New ⇒ New Project
اما اگر هنوز برنامه خود را باز نکرده اید یکی از برنامه های فوق را باز نموده و بعد از تعیین مشخصات(نامگذاری) ، تعیین حداقل sdk و نوع اکتیویتی (blank یا Empty) ، نام اکتیویتی ابتدایی و اصلی خود را UploadToServer بگذارید. بعد از لود کامل برنامه ، در مسیر res ⇒layout لایه متناظر اکتیوتی اصلی را پیدا نمود و کدهای مندرج و پیش فرض آن را پاک کرده و کدهای xml زیر را به آن اضافه کنید.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="60dp"
android:id="@+id/messageText"
android:layout_above="@+id/uploadButton"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="118dp" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Click To Upload File"
android:id="@+id/uploadButton"
android:layout_alignParentBottom="true"
android:layout_marginBottom="196dp" />
</RelativeLayout>
با اضافه کردن کدهای زیر به سراغ کلاس اصلی یعنی UploadToServer رفته و کدهای زیر را به شکل زیر به آن اضافه می کنیم.
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class UploadToServer extends Activity {
TextView messageText;
Button uploadButton;
int serverResponseCode = 0;
ProgressDialog dialog = null;
String upLoadServerUri = null;
/********** File Path *************/
final String uploadFilePath = "/mnt/sdcard/";
final String uploadFileName = "imageupload.jpg";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
uploadButton = (Button)findViewById(R.id.uploadButton);
messageText = (TextView)findViewById(R.id.messageText);
messageText.setText("Uploading file path :- '/mnt/sdcard/"+uploadFileName+"'");
upLoadServerUri = "http://psrd.ir/fixurl/upload.php";
uploadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialog = ProgressDialog.show(UploadToServer.this, "", "Uploading file...", true);
new Thread(new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
messageText.setText("uploading started.....");
}
});
uploadFile(uploadFilePath + "" + uploadFileName);
}
}).start();
}
});
}
public int uploadFile(String sourceFileUri) {
String fileName = sourceFileUri;
HttpURLConnection conn = null;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
File sourceFile = new File(sourceFileUri);
if (!sourceFile.isFile()) {
dialog.dismiss();
Log.e("uploadFile", "Source File not exist :"
+ uploadFilePath + "" + uploadFileName);
runOnUiThread(new Runnable() {
public void run() {
messageText.setText("Source File not exist :"
+uploadFilePath + "" + uploadFileName);
}
});
return 0;
}
else
{
try {
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(upLoadServerUri);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
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", fileName);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: " +
"form-data; name=\"uploaded_file\";filename=\"\" + fileName + \"\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn.getResponseMessage();
Log.i("uploadFile", "HTTP Response is : "
+ serverResponseMessage + ": " + serverResponseCode);
if(serverResponseCode == 200){
runOnUiThread(new Runnable() {
public void run() {
String msg = "File Upload Completed.\n\n See uploaded file here : \n\n"
+" http://www.psrd.ir/fixurl/uploads/"
+uploadFileName;
messageText.setText(msg);
Toast.makeText(UploadToServer.this,
"File Upload Complete.", Toast.LENGTH_SHORT).show();
}
});
}
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
dialog.dismiss();
ex.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
messageText.setText("MalformedURLException Exception :check script url.");
Toast.makeText(UploadToServer.this, "MalformedURLException",
Toast.LENGTH_SHORT).show();
}
});
Log.e("Upload file to server", "error: " + ex.getMessage(), ex);
} catch (Exception e) {
dialog.dismiss();
e.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
messageText.setText("Got Exception : see logcat ");
Toast.makeText(UploadToServer.this,
"Got Exception : see logcat ", Toast.LENGTH_SHORT).show();
}
});
}
dialog.dismiss();
return serverResponseCode;
} // End else block
}
}
سپس به سراغ فایل Androidmanifest.xml می رویم با افزودن مجوز دسترسی به اینترنت به شکل زیر :
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
امکان دسترسی را اپلیکیشن را به اینترنت تعریف می کنیم. در نهایت کدهای AndroidManifest.xml را به شکل زیر تنظیم می کنیم. توجه داشته باشد که در صورت کپی کردن کدها نام پکیج خودرا با پکیج ارائه شده در مثال مقایسه کنید و پکیج پروژه خود را در آن لحاظ کنید.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.site.psrd.uploadtoserver">
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".UploadToServer"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
حال نوبت به نوشتن اسکریپت های فایل php می شود. همانطور که قبلاً توضیح داده شد این فایل در بر روی سرور شما و در داخل پوشه public_html با پسوند php قرار می گیرد که در ذیل کدهای آن آورده شده است.
<?php
$file_path = "uploads/";
$file_path = $file_path . basename( $_FILES['uploaded_file']['name']);
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path)) {
echo "success";
} else{
echo "fail";
}
?>
حال نوبت به اجرای پروژه می رسد. اگر در اجرای پروژه ارائه شده مشکلی داشید با طرح سوالات خود در قسمت دیدگاه ها به پاسخ مورد نظر خود دست خواهید یافت.
کپی برداری از محتوای سایت psrd، ممنوع بوده و پیگرد قانونی دارد. (تنها استفاده شخصی کاربران ، مجاز است) (کپی برداری توسط سایر وب سایت ها غیرقانونی بوده و در صورت رویت به ستادسازماندهی اطلاع داده خواهد شد.
منبع اصلی این مقاله :
3 دیدگاه
حجت · آگوست 27, 2018 در 9:26 ب.ظ
سلام خسته نباشید
من برنامه اجرا کردم و ادرس سرور روی موبایل را بهش دادم ولی فایلی داخل پوشه public_html اضافه نمیشه و اینکه فایل php را که اجرا میکنم fail میزنه ممنون اگر جواب بدین
حجت · آگوست 28, 2018 در 2:13 ب.ظ
پروژه خطایی نداره و اجرا میشه فقط عملیات انجام نمیشه و عکسی داخل سرور تعیین شده اپلود نمیشه
هادی سلیمانیان · فوریه 23, 2019 در 9:06 ق.ظ
سلام ببخشید در این روش جیسون که از سایت می اید چطور میشه دریافت کرد من اسم فایلی که در سرور ذخیره شده رو بر می گردانم ولی در این اندروید نمی دونم چطور این جیسون استخراج کنم
با سپاس فراوان