【问题标题】:How to pass request string param using Retrofit for file Upload?如何使用 Retrofit 传递请求字符串参数以进行文件上传?
【发布时间】:2017-04-13 16:53:43
【问题描述】:

如何使用 Retrofit 发送请求字符串参数。我已经提交了下面的代码。这里如何添加字符串参数并发送到服务器。

应用配置:


公共类 AppConfig {

public static String BASE_URL = "http://104.239.173.64/peoplecaddie-api";

public static Retrofit getRetrofit() {

    return new Retrofit.Builder()
            .baseUrl(AppConfig.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
}

ApiConfig:

public interface ApiConfig {

    @Multipart
    @POST("/general/Candidate/fileUpload")
    Call<ServerResponse> upload(
            @Header("Authorization") String authorization,
            @PartMap Map<String, RequestBody> map
    );
}

服务器响应:


public class ServerResponse {

    // variable name should be same as in the json response from php
    @SerializedName("success")
    boolean success;
    @SerializedName("message")
    String message;

    public String getMessage() {
        return message;
    }

    public boolean getSuccess() {
        return success;
    }

}

主活动:

public class MainActivity extends AppCompatActivity {

    Button btnUpload, btnPickImage, btnPickVideo;
    String mediaPath;
    ImageView imgView;
    String[] mediaColumns = {MediaStore.Video.Media._ID};
    ProgressDialog progressDialog;
    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient client2;

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

        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Uploading...");

        btnUpload = (Button) findViewById(R.id.upload);
        btnPickImage = (Button) findViewById(R.id.pick_img);
        btnPickVideo = (Button) findViewById(R.id.pick_vdo);
        imgView = (ImageView) findViewById(R.id.preview);

        btnUpload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                uploadFile();
            }
        });

        btnPickImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent galleryIntent = new Intent(Intent.ACTION_PICK,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(galleryIntent, 0);
            }
        });

        // Video must be low in Memory or need to be compressed before uploading...
        btnPickVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent galleryIntent = new Intent(Intent.ACTION_PICK,
                        MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(galleryIntent, 1);
            }
        });

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client2 = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        try {
            // When an Image is picked
            if (requestCode == 0 && resultCode == RESULT_OK && null != data) {

                // Get the Image from data
                Uri selectedImage = data.getData();
                String[] filePathColumn = {MediaStore.Images.Media.DATA};

                Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
                assert cursor != null;
                cursor.moveToFirst();

                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                mediaPath = cursor.getString(columnIndex);
                // Set the Image in ImageView for Previewing the Media
                imgView.setImageBitmap(BitmapFactory.decodeFile(mediaPath));
                cursor.close();

            } // When an Video is picked
            else if (requestCode == 1 && resultCode == RESULT_OK && null != data) {

                // Get the Video from data
                Uri selectedVideo = data.getData();
                String[] filePathColumn = {MediaStore.Video.Media.DATA};

                Cursor cursor = getContentResolver().query(selectedVideo, filePathColumn, null, null, null);
                assert cursor != null;
                cursor.moveToFirst();

                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                mediaPath = cursor.getString(columnIndex);
                // Set the Video Thumb in ImageView Previewing the Media
                imgView.setImageBitmap(getThumbnailPathForLocalFile(MainActivity.this, selectedVideo));
                cursor.close();

            } else {
                Toast.makeText(this, "You haven't picked Image/Video", Toast.LENGTH_LONG).show();
            }
        } catch (Exception e) {
            Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG).show();
        }

    }

    // Providing Thumbnail For Selected Image
    public Bitmap getThumbnailPathForLocalFile(Activity context, Uri fileUri) {
        long fileId = getFileId(context, fileUri);
        return MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(),
                fileId, MediaStore.Video.Thumbnails.MICRO_KIND, null);
    }

    // Getting Selected File ID
    public long getFileId(Activity context, Uri fileUri) {
        Cursor cursor = context.managedQuery(fileUri, mediaColumns, null, null, null);
        if (cursor.moveToFirst()) {
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
            return cursor.getInt(columnIndex);
        }
        return 0;
    }

    // Uploading Image/Video
    private void uploadFile() {
        progressDialog.show();

        // Map is used to multipart the file using okhttp3.RequestBody
        Map<String, RequestBody> map = new HashMap<>();
        File file = new File(mediaPath);
        RequestBody requestBody = RequestBody.create(MediaType.parse("*/*"), file);
        map.put("fileContent0\"; filename=\"" + file.getName() + "\"", requestBody);

       ApiConfig getResponse = AppConfig.getRetrofit().create(ApiConfig.class);
        Call<ServerResponse> call = getResponse.upload(token, map);
        call.enqueue(new Callback<ServerResponse>() {
            @Override
            public void onResponse(Call<ServerResponse> call, Response<ServerResponse> response) {
                ServerResponse serverResponse = response.body();
                if (serverResponse != null) {
                    if (serverResponse.getSuccess()) {
                        Log.e("Response", serverResponse.getMessage());
                        Toast.makeText(getApplicationContext(), serverResponse.getMessage(), Toast.LENGTH_SHORT).show();
                    } else {
                        Log.e("Response", serverResponse.getMessage());
                        Toast.makeText(getApplicationContext(), serverResponse.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Log.v("Response", serverResponse.toString());
                }
                progressDialog.dismiss();
            }

            @Override
            public void onFailure(Call<ServerResponse> call, Throwable t) {
                Log.e("Throwable", t.toString());
            }
        });
    }



    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client2.connect();
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.delaroystudios.androidupload/http/host/path")
        );
        AppIndex.AppIndexApi.start(client2, viewAction);
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.delaroystudios.androidupload/http/host/path")
        );
        AppIndex.AppIndexApi.end(client2, viewAction);
        client2.disconnect();
    }
}

在上面的示例代码中,只是在请求正文的帮助下传递了令牌和文件。

  • 如何使用上述代码发送请求字符串参数。

这就是如何使用改造将登录参数下方的详细信息作为请求参数发送。当我尝试时,我得到了 /Throwable: com.google.gson.stream.MalformedJsonException: 使用 JsonReader.setLenient(true) 在第 1 行第 1 列路径 $ 接受格式错误的 JSON。这个例外。

  HashMap<String, String> login_params = new HashMap<String, String>();
        login_params.put("fileCount", "1");
        login_params.put("id","1743");
        login_params.put("fileType", "SAMPLE");
        login_params.put("platform", "Android");
        login_params.put("externalID", "portpolio");

【问题讨论】:

    标签: android file-upload parameters retrofit


    【解决方案1】:

    您可以使用@PartMap 注解将参数与文件请求一起传递。 PartMap 是“Key”和 RequestBody 的 Map。因此,首先,您必须创建要传递的参数的 RequestBody 对象,然后创建它的 Map 对象并将其作为参数传递。

    例如,您在 api 接口中的方法是,

    @Multipart
        @POST("upload")
        Call<ResponseBody> uploadFileWithPartMap(
                @PartMap() Map<String, RequestBody> partMap,
                @Part MultipartBody.Part file);
    

    请求会是,

    MultipartBody.Part body = prepareFilePart("photo", fileUri);
    
    // create a map of data to pass along
    RequestBody token= RequestBody.create(
            MediaType.parse(MULTIPART_FORM_DATA), "token_string");
    HashMap<String, RequestBody> map = new HashMap<>();  
    map.put("token", token);  
    
    -----------------
    
    private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {  
        // 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);
    
        // create RequestBody instance from file
        RequestBody requestFile =
            RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), file);
    
        // MultipartBody.Part is used to send also the actual file name
        return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
    }
    

    最后调用方法是,

    // finally, execute the request
    Call<ResponseBody> call = service.uploadFileWithPartMap(map, body);  
    call.enqueue(...);  
    

    希望对您有所帮助,详细参考请查看此链接https://futurestud.io/tutorials/retrofit-2-passing-multiple-parts-along-a-file-with-partmap

    【讨论】:

    • 感谢您的回复。这里 prepareFilePart("照片", fileUri);意味着什么?获取文件uri方法?你能告诉我那个方法代码吗? @srushti
    • @karthik 它从文件数据创建 MultipartBody 对象。我已经更新了我的答案,请查看。
    • 终于可以正常工作了。我用 RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); Map map = new HashMap(); map.put("fileContent0\"; filename=\"" + file.getName() + "\"", requestFile); 它工作正常
    • 这里上传文件方法我可以跟踪使用的响应。这很好用。使用 System.out.println("Rrespppppp--->"+response.body().string()); 但是在尝试转换 JSON 对象时它不起作用,错误代码如下。请让我知道如何使用此代码解析并获取成功和失败响应值。 @Srushti
    • 如果您的响应 response.body().string()‌ 给出了正确的输出,那么解析响应可能存在一些问题。确保您使用的模型在结构和属性/变量方面都是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 2020-05-21
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多