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
);
}
這是一個很大的代碼爲人們涉水通過。你是否實現了你想要的功能,並且你有一個bug,或者你想添加這個功能,但不知道如何?無論哪種方式,請嘗試將代碼縮減爲更小的示例。 – halfer
感謝您的回覆。 –
我剛纔解決了這個問題,它是由Server的問題引起的。服務器沒有創建ArrayList的對象。謝謝你的有趣。 –