将图像上传到服务器android

Posted

技术标签:

【中文标题】将图像上传到服务器android【英文标题】:Uploading Images to Server android 【发布时间】:2013-12-17 19:41:41 【问题描述】:

我想知道在不降低质量的情况下将图像上传到服务器的最佳方式是什么。 我在谷歌上搜索发现了各种发布数据的方法。但我不确定哪一个最好上传。 我遇到了

    多部分图像上传。 使用字节数组上传图片 使用 base64 编码字符串上传图片。

我已经尝试过 Base64 编码,如果图像分辨率太高,它会导致我出现 OOM(内存不足)。 任何解决此问题的教程将不胜感激。 提前致谢。

【问题讨论】:

多部分图片加载不错,你可以试试,如果需要我会提供代码 【参考方案1】:
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, 1);

从图库中选择图像的代码

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1)
        if (resultCode == Activity.RESULT_OK) 
            Uri selectedImage = data.getData();

            String filePath = getPath(selectedImage);
            String file_extn = filePath.substring(filePath.lastIndexOf(".") + 1);
            image_name_tv.setText(filePath);

            try 
                if (file_extn.equals("img") || file_extn.equals("jpg") || file_extn.equals("jpeg") || file_extn.equals("gif") || file_extn.equals("png")) 
                    //FINE
                 else 
                    //NOT IN REQUIRED FORMAT
                
             catch (FileNotFoundException e) 
                // TODO Auto-generated catch block
                e.printStackTrace();
            
        


public String getPath(Uri uri) 
    String[] projection = MediaColumns.DATA;
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    column_index = cursor
            .getColumnIndexOrThrow(MediaColumns.DATA);
    cursor.moveToFirst();
    imagePath = cursor.getString(column_index);

    return cursor.getString(column_index);

现在使用多部分表单数据发布数据

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("LINK TO SERVER");

多部分表单数据

MultipartEntity mpEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
if (filePath != null) 
    File file = new File(filePath);
    Log.d("EDIT USER PROFILE", "UPLOAD: file length = " + file.length());
    Log.d("EDIT USER PROFILE", "UPLOAD: file exist = " + file.exists());
    mpEntity.addPart("avatar", new FileBody(file, "application/octet"));

最终将数据发布到服务器

httppost.setEntity(mpEntity);
HttpResponse response = httpclient.execute(httppost);

【讨论】:

@Manoj 如果 Nitin 的解决方案对您有所帮助,请将答案标记为正确。 @DwivediJi 你也可以发布你的答案,人们会从中受益,没有冒犯。 @Iqbal 我可以想象您在 android 6.0 或更高版本上运行它,您需要遵守新的 Android 权限模型并询问用户访问读/写外部存储的权限,了解更多信息: developer.android.com/training/permissions/index.html HTTPPOST的gradle是什么? 这需要更多背景知识。例如,什么是 gradle 命令,甚至需要哪些导入才能编译?【参考方案2】:

要挑选和上传的主要活动类

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().hasSystemFeature(
                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();
        
    

用于处理上传图片并从 base64 编码数据创建图片的 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";


?>

【讨论】:

由于大部分内容已被弃用,我一直在尝试更新代码......这非常令人沮丧。 :) 我能够用“Pair”替换“NameValuePair”,并且我使用的是 HttpUrlConnection 而不是 apache 的东西。但我迷失在“帖子”部分。【参考方案3】:

使用下面的代码对你有帮助....

        BitmapFactory.Options options = new BitmapFactory.Options();

        options.inSampleSize = 4;
        options.inPurgeable = true;
        Bitmap bm = BitmapFactory.decodeFile("your path of image",options);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        bm.compress(Bitmap.CompressFormat.JPEG,40,baos); 


        // bitmap object

        byteImage_photo = baos.toByteArray();

                    //generate base64 string of image

                   String encodedImage =Base64.encodeToString(byteImage_photo,Base64.DEFAULT);

  //send this encoded string to server

【讨论】:

【参考方案4】:

试试这个方法从相机上传图片文件

package com.example.imageupload;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.message.BasicHeader;

public class MultipartEntity implements HttpEntity 

private String boundary = null;

ByteArrayOutputStream out = new ByteArrayOutputStream();
boolean isSetLast = false;
boolean isSetFirst = false;

public MultipartEntity() 
    this.boundary = System.currentTimeMillis() + "";


public void writeFirstBoundaryIfNeeds() 
    if (!isSetFirst) 
        try 
            out.write(("--" + boundary + "\r\n").getBytes());
         catch (final IOException e) 

        
    
    isSetFirst = true;


public void writeLastBoundaryIfNeeds() 
    if (isSetLast) 
        return;
    
    try 
        out.write(("\r\n--" + boundary + "--\r\n").getBytes());
     catch (final IOException e) 

    
    isSetLast = true;


public void addPart(final String key, final String value) 
    writeFirstBoundaryIfNeeds();
    try 
        out.write(("Content-Disposition: form-data; name=\"" + key + "\"\r\n")
                .getBytes());
        out.write("Content-Type: text/plain; charset=UTF-8\r\n".getBytes());
        out.write("Content-Transfer-Encoding: 8bit\r\n\r\n".getBytes());
        out.write(value.getBytes());
        out.write(("\r\n--" + boundary + "\r\n").getBytes());
     catch (final IOException e) 

    


public void addPart(final String key, final String fileName,
        final InputStream fin) 
    addPart(key, fileName, fin, "application/octet-stream");


public void addPart(final String key, final String fileName,
        final InputStream fin, String type) 
    writeFirstBoundaryIfNeeds();
    try 
        type = "Content-Type: " + type + "\r\n";
        out.write(("Content-Disposition: form-data; name=\"" + key
                + "\"; filename=\"" + fileName + "\"\r\n").getBytes());
        out.write(type.getBytes());
        out.write("Content-Transfer-Encoding: binary\r\n\r\n".getBytes());

        final byte[] tmp = new byte[4096];
        int l = 0;
        while ((l = fin.read(tmp)) != -1) 
            out.write(tmp, 0, l);
        
        out.flush();
     catch (final IOException e) 

     finally 
        try 
            fin.close();
         catch (final IOException e) 

        
    


public void addPart(final String key, final File value) 
    try 
        addPart(key, value.getName(), new FileInputStream(value));
     catch (final FileNotFoundException e) 

    


public long getContentLength() 
    writeLastBoundaryIfNeeds();
    return out.toByteArray().length;


public Header getContentType() 
    return new BasicHeader("Content-Type", "multipart/form-data; boundary="
            + boundary);


public boolean isChunked() 
    return false;


public boolean isRepeatable() 
    return false;


public boolean isStreaming() 
    return false;


public void writeTo(final OutputStream outstream) throws IOException 
    outstream.write(out.toByteArray());


public Header getContentEncoding() 
    return null;


public void consumeContent() throws IOException,
        UnsupportedOperationException 
    if (isStreaming()) 
        throw new UnsupportedOperationException(
                "Streaming entity does not implement #consumeContent()");
    


public InputStream getContent() throws IOException,
        UnsupportedOperationException 
    return new ByteArrayInputStream(out.toByteArray());



使用类进行上传

private void doFileUpload(File file_path) 

    Log.d("Uri", "Do file path" + file_path);

    try 

        HttpClient client = new DefaultHttpClient();
        //use your server path of php file
        HttpPost post = new HttpPost(ServerUploadPath);

        Log.d("ServerPath", "Path" + ServerUploadPath);

        FileBody bin1 = new FileBody(file_path);
        Log.d("Enter", "Filebody complete " + bin1);

        MultipartEntity reqEntity = new MultipartEntity();
        reqEntity.addPart("uploaded_file", bin1);
        reqEntity.addPart("email", new StringBody(useremail));

        post.setEntity(reqEntity);
        Log.d("Enter", "Image send complete");

        HttpResponse response = client.execute(post);
        resEntity = response.getEntity();
        Log.d("Enter", "Get Response");
        try 

            final String response_str = EntityUtils.toString(resEntity);
            if (resEntity != null) 
                Log.i("RESPONSE", response_str);
                JSONObject jobj = new JSONObject(response_str);
                result = jobj.getString("ResponseCode");
                Log.e("Result", "...." + result);

            
         catch (Exception ex) 
            Log.e("Debug", "error: " + ex.getMessage(), ex);
        
     catch (Exception e) 
        Log.e("Upload Exception", "");
        e.printStackTrace();
    

上传服务

   <?php
$image_name = $_FILES["uploaded_file"]["name"]; 
$tmp_arr = explode(".",$image_name);
$img_extn = end($tmp_arr);
$new_image_name = 'image_'. uniqid() .'.'.$img_extn;    
$flag=0;                 

if (file_exists("Images/".$new_image_name))

           $msg=$new_image_name . " already exists."
           header('Content-type: application/json');        
           echo json_encode(array("ResponseCode"=>"2","ResponseMsg"=>$msg));        
else  
move_uploaded_file($_FILES["uploaded_file"]["tmp_name"],"Images/". $new_image_name);
                   $flag = 1;
   

if($flag == 1)                    
            require 'db.php';   
            $static_url =$new_image_name;
            $conn=mysql_connect($db_host,$db_username,$db_password) or die("unable to connect localhost".mysql_error());
            $db=mysql_select_db($db_database,$conn) or die("unable to select message_app"); 
            $email = "";
            if((isset($_REQUEST['email'])))
            
                     $email = $_REQUEST['email'];
            

    $sql ="insert into alert(images) values('$static_url')";

     $result=mysql_query($sql);

     if($result)
    echo json_encode(array("ResponseCode"=>"1","ResponseMsg"=> "Insert data successfully.","Result"=>"True","ImageName"=>$static_url,"email"=>$email));
        else
       

         echo json_encode(array("ResponseCode"=>"2","ResponseMsg"=> "Could not insert data.","Result"=>"False","email"=>$email));
        

    else
    echo json_encode(array("ResponseCode"=>"2","ResponseMsg"=> "Erroe While Inserting Image.","Result"=>"False"));
    
    ?>

【讨论】:

org.apache.http 在 API 版本 23 中已弃用。您能否更新此示例以使用 HttpURLConnection? @MustModify google useLibrary 'org.apache.http.legacy' 为什么要使用标记为“旧版”的库?没有替代品吗? 何时使用旧版?当您刚刚在具有 32 位 Ubuntu 的旧 Celeron 上安装了 gradle,并且只能使用旧版本的构建工具时。它100%有效。那时:) 剩下的代码在哪里?这里引用了各种未定义的变量。他们在做什么?我可以弄清楚一些,但我对此理解得不够深入,无法知道什么是必要的,什么是无关紧要的(如果我知道了,我就不会在这里!)。【参考方案5】:
//Kotlin Version


   private fun setImageForUploading (imagePath:String):String

        val options = BitmapFactory.Options();

        options.inSampleSize = 2
        //options.inPurgeable = true //deprecated

        val bitmap = BitmapFactory.decodeFile(imagePath,options)

        val byteArrayOutPutStream = ByteArrayOutputStream()

        bitmap.compress(Bitmap.CompressFormat.PNG,90,byteArrayOutPutStream)

        // bitmap object
        val byteImagePhoto = byteArrayOutPutStream.toByteArray()

        //generate base64 string of image
        val encodedImage = Base64.encodeToString(byteImagePhoto,Base64.DEFAULT)

        return encodedImage

    

【讨论】:

这是……怎么说……不完整?是的,非常不完整。剩下的代码在哪里?

以上是关于将图像上传到服务器android的主要内容,如果未能解决你的问题,请参考以下文章

将图像从android上传到服务器php时出错?

将图像从 android 上传到 PHP 服务器

在不使用字符串的情况下将图像上传到android中的服务器

将图像从 Android(使用 Android 异步 Http 客户端)上传到 rails 服务器(使用回形针)

在android中将多个图像上传到服务器的最快方法

Android:上传到服务器的图像始终为 0 字节