2017-06-25 34 views
0

我想使用Retrofit2將多圖像從Android上傳到Spring Server,但它不起作用。如何將Android上的多圖像上傳到Spring Server?

我指的是這個網站:https://futurestud.io/tutorials/retrofit-2-how-to-upload-multiple-files-to-server

我的代碼如下:

package com.example.gdtbg.fileupload; 

import android.Manifest; 
import android.content.ContentResolver; 
import android.content.ContentValues; 
import android.content.Context; 
import android.content.pm.PackageManager; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.support.annotation.NonNull; 
import android.support.v4.app.ActivityCompat; 
import android.support.v4.content.ContextCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.Toast; 

import com.ipaulpro.afilechooser.utils.FileUtils; 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.util.ArrayList; 
import java.util.List; 

import gun0912.tedbottompicker.TedBottomPicker; 
import okhttp3.MediaType; 
import okhttp3.MultipartBody; 
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 { 

    private static final int MY_PERMISSIONS_REQUEST = 100; 

    private int PICK_IMAGE_FROM_GALLERY_REQUEST = 1; 

    ArrayList<Uri> test; 



    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     test = new ArrayList<Uri>(); 

     if (ContextCompat.checkSelfPermission(MainActivity.this, 
        Manifest.permission.READ_EXTERNAL_STORAGE) 
        != PackageManager.PERMISSION_GRANTED) { 
       ActivityCompat.requestPermissions(MainActivity.this, 
        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
        MY_PERMISSIONS_REQUEST); 
     } 

     Button uploadbutton = (Button) findViewById(R.id.submit); 



     uploadbutton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 


       TedBottomPicker tedBottomPicker = new TedBottomPicker.Builder(MainActivity.this) 
         .setOnMultiImageSelectedListener(new TedBottomPicker.OnMultiImageSelectedListener() { 
          @Override 
          public void onImagesSelected(ArrayList<Uri> uriList) { //this function return Uri file uri type("file://") 

           uploadAlbum(uriList); 


          } 
         }) 
         .setSelectMaxCount(3) 
         .setEmptySelectionText("선택된게 없습니다! 이미지를 선택해 주세요!") 
         .create(); 



       tedBottomPicker.show(getSupportFragmentManager()); 



      } 
     }); 

    } 



    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     switch (requestCode) { 

      case MY_PERMISSIONS_REQUEST: { 

       if (grantResults.length > 0 
         && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 

       } else { 

       } 
       return; 

      } 

     } 

    } 

    @NonNull 
    private RequestBody createPartFromString(String descriptionString) { 
     return RequestBody.create(
       okhttp3.MultipartBody.FORM, descriptionString); 
    } 

    public static Uri getImageContentUri(Context context, File imageFile) throws FileNotFoundException{ 
     String filePath = imageFile.getAbsolutePath(); 
     Cursor cursor = context.getContentResolver().query(
       MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
       new String[] { MediaStore.Images.Media._ID }, 
       MediaStore.Images.Media.DATA + "=? ", 
       new String[] { filePath }, null); 

     if (cursor != null && cursor.moveToFirst()) { 
      int id = cursor.getInt(cursor 
        .getColumnIndex(MediaStore.MediaColumns._ID)); 
      Uri baseUri = Uri.parse("content://media/external/images/media"); 
      return Uri.withAppendedPath(baseUri, "" + id); 
     } else { 
      if (imageFile.exists()) { 
       ContentValues values = new ContentValues(); 
       values.put(MediaStore.Images.Media.DATA, filePath); 
       return context.getContentResolver().insert(
         MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); 
      } else { 
       return null; 
      } 
     } 
    } 


    private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) throws FileNotFoundException { 
     // https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java 
     // use the FileUtils to get the actual file by uri 

     File file = FileUtils.getFile(this, fileUri); 

     ContentResolver cr = getContentResolver(); 

     Uri castedUri = getImageContentUri(getApplicationContext(), file); 

     // create RequestBody instance from file 
     try { 

      Log.d("testfile", castedUri.toString()); 


      if(cr.getType(castedUri)==null) 
      { 
       Log.d("testfile", "content uri is null"); 
       Log.d("testfile", cr.getType(castedUri).toString()); 

      } 
      else 
      { 

       Log.d("testfile", "content uri is not null"); 
       Log.d("testfile", cr.getType(castedUri).toString()); 


      } 





      RequestBody requestFile = 
      RequestBody.create(MediaType.parse(cr.getType(castedUri)),file); 




      // MultipartBody.Part is used to send also the actual file name 
      return MultipartBody.Part.createFormData(partName, file.getName(), requestFile); 

     } catch (Exception e) { 
      e.printStackTrace(); 

      return null; 
     } 
    } 


    private void uploadAlbum(List<Uri> fileUris) { 
     final EditText description = (EditText) findViewById(R.id.editText); 

     Retrofit.Builder builder = new Retrofit.Builder() 
       .baseUrl("http://192.168.0.3:8089/Test/") 
       .addConverterFactory(GsonConverterFactory.create()); 

     Retrofit retrofit = builder.build(); 

     UserClient client = retrofit.create(UserClient.class); 

     ArrayList<MultipartBody.Part> parts = new ArrayList<>(); 

     Log.d("giduck", "Hello World!"); 
     Log.d("giduck", "" + fileUris.size()); 


     for (int i = 0; i < fileUris.size(); i++) { 

      Log.d("sendTest", fileUris.get(i).toString()); 
      Log.d("sendTest", "" + fileUris.size()); 

      try { 
       parts.add(prepareFilePart(""+i, fileUris.get(i))); 

      } catch (Exception e) { 

       e.printStackTrace(); 
      } 
      Log.d("giduckfinal", "" + fileUris.get(i).toString()); 
      Log.d("giduckfinal", "in loop"); 


     } 

     Log.d("giduckfinal", "this is final position 1"); 

     Call<ResponseBody> call = client.uploadAlbum(

       createPartFromString(description.getText().toString()), 
       parts); 

     Log.d("final", "this is final position 2"); 


     call.enqueue(new Callback<ResponseBody>() { 

       @Override 
       public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { 
        Toast.makeText(MainActivity.this, "Success that Upload Image to Server", Toast.LENGTH_SHORT).show(); 

      } 

      @Override 
      public void onFailure(Call<ResponseBody> call, Throwable t) { 
       Toast.makeText(MainActivity.this, "Fail that Upload to Server", Toast.LENGTH_SHORT).show(); 

      } 
     }); 

    } 

} 
  
  
package com.example.gdtbg.fileupload; 

import java.util.List; 

import okhttp3.MultipartBody; 
import okhttp3.RequestBody; 
import okhttp3.ResponseBody; 
import retrofit2.Call; 
import retrofit2.http.Multipart; 
import retrofit2.http.POST; 
import retrofit2.http.Part; 

/** 
* Created by gdtbg on 2017-06-21. 
*/ 

public interface UserClient { 

    /* @Multipart 
    @POST("uploadForm") 
    Call<ResponseBody> uploadPhoto(
      @Part("description") RequestBody description, 
      @Part MultipartBody.Part photo 

      ); 

    @Multipart 
    @POST("uploadForm") 
    Call<ResponseBody> uploadPhotos(
      @Part MultipartBody.Part profile, 
      @Part MultipartBody.Part panorama 

    ); */ 

    @Multipart 
    @POST("uploadForm") 
    Call<ResponseBody> uploadAlbum(
      @Part("description") RequestBody description, 
      @Part List<MultipartBody.Part> files 

    ); 



} 
+0

這是一個很大的代碼爲人們涉水通過。你是否實現了你想要的功能,並且你有一個bug,或者你想添加這個功能,但不知道如何?無論哪種方式,請嘗試將代碼縮減爲更小的示例。 – halfer

+0

感謝您的回覆。 –

+0

我剛纔解決了這個問題,它是由Server的問題引起的。服務器沒有創建ArrayList的對象。謝謝你的有趣。 –

回答

0

我使用這個代碼和它的作品對我來說

upload.php的

<?php 

$attachment = $_FILES['attachment']; 
define ("MAX_SIZE","9000"); 
$valid_formats = array("jpg", "png", "gif", "bmp","jpeg"); 
// Method to extract the uploaded file extention 
function getExtension($str) 
    { 
    $i = strrpos($str,"."); 
    if (!$i) { return ""; } 
    $l = strlen($str) - $i; 
    $ext = substr($str,$i+1,$l); 
    return $ext; 
} 

// Method to extract the uploaded file parameters 
function getFileAttributes($file) 
{ 
$file_ary = array(); 
$file_count = count($file['name']); 
$file_key = array_keys($file); 

for($i=0;$i<$file_count;$i++) 
{ 
    foreach($file_key as $val) 
    { 
     $file_ary[$i][$val] = $file[$val][$i]; 
    } 
} 
return $file_ary; 
} 

// Check if the POST Global variable were set 
if(!empty($attachment) && isset($_POST['dirname'])) 
    { 
$dirname = $_POST['dirname']; 

$uploaddir = "/var/www/html/uploads/".$dirname."/"; 

//Check if the directory already exists. 
if(!is_dir($uploaddir)){ 
    //Directory does not exist, so create it. 
    mkdir($uploaddir, 0777, true); 
} 

$file_attributes = getFileAttributes($attachment); 
//print_r($file_attributes); 

$count = count($file_attributes); 
$response["status"] = array(); 
$response["count"] = $count; // Count the number of files uploaded 
array_push($response["status"], $file_attributes); 

$file_dirs = array(); 

foreach($file_attributes as $val) 
{  
    $old_file = $val['name']; 
    $ext = getExtension($old_file); 
    $ext = strtolower($ext); 

    if(in_array($ext, $valid_formats)) 
    { 
     $response["files"] = array(); 
     $new_file = date('YmdHis',time()).mt_rand(10,99).'.'.$ext; 
     move_uploaded_file($val['tmp_name'], $uploaddir.$new_file); 
     $file_dirs[] = 'http://192.168.50.10/gallery/uploads/'.$dirname."/".$new_file; 
    } 
    else 
    { 
     $file_dirs[] = 'Invalid file: '.$old_file; 
    } 
} 

    array_push($response["files"], $file_dirs); 

    echo json_encode($response); 
    } 
?> 

然後在xml把這個

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout 
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="toegy.com.testmultiupload.MainActivity"> 

<TextView 
    android:id="@+id/select" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="select" 
    app:layout_constraintBottom_toBottomOf="parent" 
    app:layout_constraintLeft_toLeftOf="parent" 
    app:layout_constraintRight_toRightOf="parent" 
    app:layout_constraintTop_toTopOf="parent" /> 

    </android.support.constraint.ConstraintLayout> 

,並在你的活動把這個

public class MainActivity extends AppCompatActivity { 
TextView select; 
int PICK_IMAGE_MULTIPLE = 1; 
String imageEncoded; 
List<String> imagesEncodedList; 
ProgressDialog pDialog; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    select = (TextView) findViewById(R.id.select); 
    pDialog = new ProgressDialog(MainActivity.this); 
    select.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      Intent intent = new Intent(); 
      intent.setType("image/*"); 
      intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); 
      intent.setAction(Intent.ACTION_GET_CONTENT); 
      startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_MULTIPLE); 
     } 
    }); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    try { 
     if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == RESULT_OK && null != data) { 
      Log.e("++data", data.getClipData().getItemCount() + ""); 
      List<Uri> uriList = new ArrayList<Uri>(); 

      for (int i = 0; i < data.getClipData().getItemCount(); i++) { 
       Uri selectedImage = data.getClipData().getItemAt(i).getUri(); 
       Log.e("uri",selectedImage+""); 
       uriList.add(i,selectedImage); 

      } 
      uploadPhotos(uriList,"photos"); 


     } else { 
      Toast.makeText(this, "You haven't picked Image", Toast.LENGTH_LONG).show(); 

     } 
    } catch (Exception e) { 
     Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG).show(); 
    } 

    super.onActivityResult(requestCode, resultCode, data); 
} 

public void uploadPhotos(final List<Uri> uriList, final String folderName) { 
    pDialog.setMessage("uploading ..............."); 
    pDialog.show(); 
    List<MultipartBody.Part> parts = new ArrayList<>(); 
    for (Uri uri : uriList) { 
     parts.add(prepareFilePart("attachment[]", uri)); // Note: attachment[]. Not attachment 
    } 

    RequestBody requestBodyFolderName = createPartFromString(folderName); 
    HashMap<String, RequestBody> requestMap = new HashMap<>(); 
    requestMap.put("dirname", requestBodyFolderName); // Note: dirname 

    FileUploadService service = RetrofitClient.getApiService(); 
    Call<ResponseBody> call = service.uploadMultipleFilesDynamic(requestMap, parts); 

    call.enqueue(new Callback<ResponseBody>() { 
     @Override 
     public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { 

      if (response.code() == 200) { 
       // multiple dynamic uploads were successful 
       Log.e("status", "done"); 
       pDialog.hide(); 
      } else { 
       Log.e("status", "not done " + response.code()); 
       pDialog.hide(); 

      } 
      Toast.makeText(MainActivity.this,response.code()+"",Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onFailure(Call<ResponseBody> call, Throwable t) { 

      Log.e("status", "not done " + t.toString()); 


     } 
    }); 
} 
private String getRealPathFromURI(Uri contentURI) { 
    String result; 
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null); 
    if (cursor == null) { // Source is Dropbox or other similar local file path 
     result = contentURI.getPath(); 
    } else { 
     cursor.moveToFirst(); 
     int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
     result = cursor.getString(idx); 
     cursor.close(); 
    } 
    return result; 
} 
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) { 

    File file = new File(getRealPathFromURI(fileUri)); 
    // create RequestBody instance from file 
    RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file); 

    // MultipartBody.Part is used to send also the actual file name 
    return MultipartBody.Part.createFormData(partName, file.getName(), requestFile); 
} 

private RequestBody createPartFromString(String descriptionString) { 
    return RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString); 
} 

}

,將工作知府