gpt4 book ai didi

带有 Retrofit2 OkHttp3 的 Android - 多部分 POST 错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:57:29 28 4
gpt4 key购买 nike

我在 Android 上将 Retrofit2 与 OkHttp 一起用于 HTTP 请求。在这里,我正在执行带有文档上传的 POST 请求。我遇到了以下错误:

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)

完整调试日志已上传here

API 服务器要求 HTTP POST 多部分请求采用这种格式:

enter image description here

我的代码 fragment 如下:

1) 创建 Retrofit Handler 类:

Interceptor headerInterceptor = new Interceptor() {
@Override
public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();

String sessionKey = JStockApplication.instance().getTradingOptions().getSessionKey();

okhttp3.Request request = original.newBuilder()
//.header("Accept", "application/json")
.header("Content-Type", "multipart/form-data")
.header("x-mysolomeo-session-key", sessionKey)
.method(original.method(), original.body())
.build();

return chain.proceed(request);
}
};

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

// add static common headers
httpClient.addInterceptor(headerInterceptor);

// add Logging for development, Log Level: NONE, BASIC, HEADERS, BODY
HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(logInterceptor);

Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl("http://api.drivewealth.io/v1/")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build());

Retrofit retrofit = builder.build();

DriveWealthApi api = retrofit.create(DriveWealthApi.class);

2) Retrofit方法的接口(interface)类:

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);
}

3) 在我的 Fragment 类中,在 onCreate() 中调用 POST 请求:

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) {
......
}

知道这里出了什么问题吗?谢谢!

最佳答案

引用Retrofit 2 can't upload a file with two additional separate string parameters后,我是按照@TommySM的建议实现的。我用这个解决了我的问题:

// 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);

那些字符串参数应该指定为 Content-Type: text/plain 而不是 Content-Type: multipart/form-data

详情见截图:

1) 有问题的 POST

enter image description here

2) 正确的 POST

enter image description here

关于带有 Retrofit2 OkHttp3 的 Android - 多部分 POST 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43320205/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com