Android与OkHttp3的改进-多部分POST错误

Android与OkHttp3的改进-多部分POST错误,android,retrofit2,multipartform-data,multipart,okhttp3,Android,Retrofit2,Multipartform Data,Multipart,Okhttp3,我正在Android上使用OkHttp的Reformation2进行HTTP请求。在这里,我做了一个文件上传后的要求。我在下面遇到了错误: D/OkHttp: <-- 500 Server Error http://api.drivewealth.io/v1/documents (4289ms) D/OkHttp: Date: Tue, 11 Apr 2017 03:29:48 GMT D/OkHttp: Cache-Control: must-revalidate,no-cache,no

我正在Android上使用OkHttp的Reformation2进行HTTP请求。在这里,我做了一个文件上传后的要求。我在下面遇到了错误:

D/OkHttp: <-- 500 Server Error http://api.drivewealth.io/v1/documents (4289ms)
D/OkHttp: Date: Tue, 11 Apr 2017 03:29:48 GMT
D/OkHttp: Cache-Control: must-revalidate,no-cache,no-store
D/OkHttp: Content-Type: text/html; charset=ISO-8859-1
D/OkHttp: Server: Jetty(9.2.17.v20160517)
D/OkHttp: Content-Length: 9323
D/OkHttp: Connection: keep-alive
D/OkHttp: <html>
D/OkHttp: <head>
D/OkHttp: <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
D/OkHttp: <title>Error 500 Server Error</title>
D/OkHttp: </head>
D/OkHttp: <body><h2>HTTP ERROR 500</h2>
D/OkHttp: <p>Problem accessing /v1/documents. Reason:
D/OkHttp: <pre>    Server Error</pre></p><h3>Caused by:</h3><pre>org.apache.cxf.interceptor.Fault: Couldn&apos;t determine the boundary from the message!
D/OkHttp:     at org.apache.cxf.interceptor.AttachmentInInterceptor.handleMessage(AttachmentInInterceptor.java:60)
D/OkHttp:     at org.apache.cxf.jaxrs.ext.MessageContextImpl.createAttachments(MessageContextImpl.java:279)
D/OkHttp:     at org.apache.cxf.jaxrs.ext.MessageContextImpl.get(MessageContextImpl.java:77)
D/OkHttp:     at org.apache.cxf.jaxrs.impl.tl.ThreadLocalMessageContext.get(ThreadLocalMessageContext.java:42)
D/OkHttp:     at org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils.getMultipartBody(AttachmentUtils.java:114)
D/OkHttp:     at org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils.getAttachments(AttachmentUtils.java:119)
2) 改装方法的接口类:

// create RequestBody instance from file
RequestBody requestFile = RequestBody.create(
            mediaType,
            myFile);

// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part file = MultipartBody.Part.createFormData(
            "documentImage",
            myFile.getName(),
            requestFile);

// add another part within the multipart request
RequestBody token = RequestBody.create(
            MediaType.parse("text/plain"),   // Fixed here
            //okhttp3.MultipartBody.FORM,    => PROBLEMATIC
            userID);

RequestBody docType = RequestBody.create(
            MediaType.parse("text/plain"),   // Fixed here
            //okhttp3.MultipartBody.FORM,    => PROBLEMATIC
            docTypeStr);

// token, documentType, file
this.call = driveWealthApi.addDocument(token, docType, file);
导入okhttp3.MultipartBody;
导入okhttp3.RequestBody;
进口okhttp3.0响应电子书;
2.电话;;
导入文件2.http.Body;
导入文件2.http.Multipart;
导入文件2.http.POST;
导入2.http.Part;
公共接口DriveWealthApi{
@多部分
@邮寄(“文件”)
调用addDocument(
@部分(“令牌”)请求主体令牌,
@零件(“文档类型”)请求主体文档类型,
@Part MultipartBody.Part文件);
}
3) 在我的片段类中,POST请求在onCreate()中调用:

公共类AddDocumentTaskFragment扩展片段实现回调{
@凌驾
创建时的公共void(Bundle savedInstanceState){
........
........
Bundle=this.getArguments();
String userID=bundle.getString(INTENT\u EXTRA\u USER\u ID);
String docType=bundle.getString(INTENT\u EXTRA\u DOCUMENT\u TYPE);
String fileUri=bundle.getString(INTENT\u EXTRA\u FILE\u URI);
Uri=Uri.parse(fileUri);
字符串filePath=MyUtils.getPath(this.getActivity(),uri);
if(filePath==null | | filePath.isEmpty()){
返回;
}
最终文件myFile=新文件(文件路径);
MediaType MediaType=MediaType.parse(getActivity().getContentResolver().getType(uri));
if(myFile==null){
返回;
}
//从文件创建RequestBody实例
RequestBody requestFile=RequestBody.create(mediaType,myFile);
//Part还用于发送实际的文件名
MultipartBody.Part fileBody=MultipartBody.Part.createFormData(“documentImage”,myFile.getName(),requestFile);
//在多部分请求中添加另一部分
RequestBody-tokenBody=RequestBody.create(okhttp3.MultipartBody.FORM,userID);
RequestBody docTypeBody=RequestBody.create(okhttp3.MultipartBody.FORM,docType);
//参数:令牌、文档类型、文件
this.call=driveWealthApi.addDocument(tokenBody、docTypeBody、fileBody);
this.call.enqueue(this);
}
@凌驾
公共void onResponse(调用、响应){
.....
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
......
}
知道这里出了什么问题吗?谢谢!

参考后,我根据@TommySM建议实施了。我通过以下方法解决了我的问题:

这些字符串参数应指定为
内容类型:text/plain
,而不是
内容类型:multipart/form data

有关详细信息,请参见屏幕截图:

1) 有问题的职位

2) 正确的职位


您好!我无法检查您的DriveWealth API,但是,它的示例中似乎有奇怪的边界定义(
boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
与流中的边界相同),请在@BNK上阅读已接受的答案,感谢您的反馈。我的问题已在此处解决,如下所示,再次感谢您的帮助!:)
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;

public interface DriveWealthApi {
    @Multipart
    @POST("documents")
    Call<ResponseBody> addDocument(
            @Part("token") RequestBody token,
            @Part("documentType") RequestBody documentType,
            @Part MultipartBody.Part file);
}
public class AddDocumentTaskFragment extends Fragment implements Callback<ResponseBody> {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ........
        ........

        Bundle bundle = this.getArguments();
        String userID = bundle.getString(INTENT_EXTRA_USER_ID);
        String docType = bundle.getString(INTENT_EXTRA_DOCUMENT_TYPE);
        String fileUri = bundle.getString(INTENT_EXTRA_FILE_URI);
        Uri uri = Uri.parse(fileUri);

        String filePath = MyUtils.getPath(this.getActivity(), uri);

        if (filePath == null || filePath.isEmpty()) {
            return;
        }

        final File myFile = new File(filePath);
        MediaType mediaType = MediaType.parse(getActivity().getContentResolver().getType(uri));

        if (myFile == null) {
            return;
        }

        // create RequestBody instance from file
        RequestBody requestFile = RequestBody.create(mediaType, myFile);

        // MultipartBody.Part is used to send also the actual file name
        MultipartBody.Part fileBody = MultipartBody.Part.createFormData("documentImage", myFile.getName(), requestFile);

        // add another part within the multipart request
        RequestBody tokenBody = RequestBody.create(okhttp3.MultipartBody.FORM, userID);

        RequestBody docTypeBody = RequestBody.create(okhttp3.MultipartBody.FORM, docType);

        // params: token, documentType, file
        this.call = driveWealthApi.addDocument(tokenBody, docTypeBody, fileBody);
        this.call.enqueue(this);
    }

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

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        ......
    }
// create RequestBody instance from file
RequestBody requestFile = RequestBody.create(
            mediaType,
            myFile);

// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part file = MultipartBody.Part.createFormData(
            "documentImage",
            myFile.getName(),
            requestFile);

// add another part within the multipart request
RequestBody token = RequestBody.create(
            MediaType.parse("text/plain"),   // Fixed here
            //okhttp3.MultipartBody.FORM,    => PROBLEMATIC
            userID);

RequestBody docType = RequestBody.create(
            MediaType.parse("text/plain"),   // Fixed here
            //okhttp3.MultipartBody.FORM,    => PROBLEMATIC
            docTypeStr);

// token, documentType, file
this.call = driveWealthApi.addDocument(token, docType, file);