解決策が見つかるまで、可能な代替解決策の質問の下部にある編集を読む.
これは、POSTManを使用した2つのパラメーターを持つ成功した投稿ファイルです。私はレトロフィットで同じことをしようとしていますが、BadRequestを受け取ります。
PostMan設定:
ここで、これをAndroidで実行していますが、失敗しています:
Retrofit Service Interface:
@Multipart
@POST("jobDocuments/upload")
Call<ResponseBody> upload(@Part("file") MultipartBody.Part file,@Part("folder") MultipartBody.Part folder,@Part("name") MultipartBody.Part name);
これは、上記のサービスが生成されたネットワーク要求を実行するための私の@Backgroundメソッドです
CustDataClient service =
ServiceGenerator.createService(CustDataClient.class);
File file = new File(fileUri.getPath());
// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part fileData =
MultipartBody.Part.createFormData("file", fileName, requestFile);
MultipartBody.Part folder =
MultipartBody.Part.createFormData("folder", "LeadDocuments");
MultipartBody.Part name =
MultipartBody.Part.createFormData("name", fileName);
// finally, execute the request
Call<ResponseBody> call = service.upload(fileData,folder,name);
try {
Response<ResponseBody> rr = call.execute();
ResponseBody empJobDocsResult = rr.body();//Bad Request here :(
Log.v("Upload", "success");
} catch (Exception ex) {
Log.e("Upload error:", ex.getMessage());
}
これが私のWeb APIメソッドです:
[Route("upload")]
[HttpPost]
public IHttpActionResult Upload()
{
if (HttpContext.Current.Request.Files.AllKeys.Any())
{
// Get the uploaded image from the Files collection
var httpPostedFile = HttpContext.Current.Request.Files["file"];
if (httpPostedFile != null)
{
// Validate the uploaded image(optional)
var folder = HttpContext.Current.Request.Form["folder"];
var fileName = HttpContext.Current.Request.Form["name"];
fileName = string.IsNullOrEmpty(fileName) ? httpPostedFile.FileName : fileName;
// Get the complete file path
var fileSavePath = Path.Combine(HttpContext.Current.Server.MapPath("~/Files/" + folder), fileName);
// Save the uploaded file to "UploadedFiles" folder
httpPostedFile.SaveAs(fileSavePath);
return Ok(new OkMessage { Message = "File uploaded successfully", Path = "/Files/" + folder + "/" + fileName });
}
}
return BadRequest("File not uploaded");
}
私が間違っている場所とこれを達成する方法を助けてください、レトロフィットの簡単な代替手段はありますか?
[編集]このコードは正常に機能しています。おかげで koush/ion :
Ion.with(getContext())
.load("POST", "http://www.dgheating.com/api/jobDocuments/upload")
.setMultipartParameter("folder", "LeadDocuments")
.setMultipartParameter("name", fileName)
.setMultipartFile("file", new File(imagePath))
.asJsonObject()
.setCallback(...);
私はここで同様の問題に直面しました: Retrofit2 OkHttp3を搭載したAndroid-Multipart POST Error
@TommySMの提案を受けて問題を解決しました。それでも不明な場合は、これが解決策だと思います:
_@Multipart
@POST("jobDocuments/upload")
Call<ResponseBody> upload(
@Part MultipartBody.Part file,
@Part("folder") RequestBody folder,
@Part("name") RequestBody name);
File file = new File(fileUri.getPath());
// Assume your file is PNG
RequestBody requestFile =
RequestBody.create(MediaType.parse("image/png"), file);
MultipartBody.Part fileData =
MultipartBody.Part.createFormData("file", fileName, requestFile);
RequestBody folder = RequestBody.create(
MediaType.parse("text/plain"),
"LeadDocuments");
RequestBody name = RequestBody.create(
MediaType.parse("text/plain"),
fileName);
// finally, execute the request
Call<ResponseBody> call = service.upload(fileData, folder, name);
_
重要な部分は、StringパラメーターのMediaType
にMediaType.parse("text/plain")
を使用することです(フォルダーと名前のパラメーターはそうだと思います)。_okhttp3.MultipartBody.FORM
_の使用は間違いです。
比較のためにこれらのスクリーンショットを参照してください:
1)問題のあるPOST
2)正しいPOST
だから、手遅れではないことを願っています-もしそうなら-それは他の誰かを助けるかもしれない:)これについての私の2セントはしばらく前に同じ問題を抱えた後です:
_@Part
_のみを使用したサービス定義(サーバーの期待に応じてフィールド名を変更します)
_//Single image MultiPart
@Multipart
@POST("user/imageupload")
Call<ResponseBody> upload(@Part("userfile") RequestBody file, @Part("userid") RequestBody description);
_
そして、魔法のトリックのために、両方の部分をRequestBody
として参照し、それぞれの型にMediaType.parse()
を使用し、リクエスト自体の_@Multipart
_定義に依存します、_form-data
_の必要はなく、同じことが複数のファイル、および複数のフィールドで機能します。
_private static final String IMG_JPEG = "image/jpeg";
private static final String TXT_PLAIN = "text/plain";
public void uploadImageMultipart(Uri uri, final CustomEventListener<String> listener)
{
RequestBody fileBody;
RequestBody textBody;
File file = new File(uri.getPath());
Call<ResponseBody> requestCall;
fileBody = RequestBody.create(okhttp3.MediaType.parse(IMG_JPEG), file);
textBody = RequestBody.create(okhttp3.MediaType.parse(TXT_PLAIN), String.valueOf(SettingsManager.getUserID()));
requestCall = serviceCaller.upload(fileBody, textBody);
requestCall.enqueue(new Callback<ResponseBody>()
{
@Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse)
{
try
{
String response = rawResponse.body().string();
//from here it's your show....
listener.getResult("Got it");
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable throwable)
{
}
});
}
_
(リスナーを使用して、アプリの別の部分(たとえば、呼び出しアクティビティ)にコールバック応答を返します)。
これは間違いなくファイルとテキストフィールドを送信しますが、他の問題はおそらくサーバー側に起因するでしょう。
お役に立てれば!
Retrofit 2を使用するには、OkHttpのRequestBodyクラスまたはMultipartBody.Partクラスを使用し、ファイルをリクエスト本文にカプセル化する必要があります。ファイルのアップロードのインターフェース定義を見てみましょう。あなたは見ましたか https://futurestud.io/blog/retrofit-2-how-to-upload-files-to-server
レトロフィット用インターフェース(API)
public interface API {
String NAME = "name";
String FOLDER = "folder";
@Multipart
@POST("/api/jobDocuments/upload")
Call<JsonResponse> uploadFile(
@Part(NAME) String name,
@Part(FOLDER) String folder,
@Part MultipartBody.Part file);
}
応答クラス(JsonResponse)
public class JsonResponse {
@SerializedName("$id")
public String id;
@SerializedName("Message")
public String message;
@SerializedName("Path")
public String path;
public JsonResponse(String id, String message, String path) {
this.id = id;
this.message = message;
this.path = path;
}
}
アプリケーションからのAPI呼び出し
Retrofit retrofit;
private void postImage() {
String URL = "http://www.dgheating.com/";
//your file location
File file = new File(Environment.getExternalStorageDirectory() + "/Image.png");
//parameters
String NAME = file.getName();
String FOLDER = "LeadDocuments";
String FILE = "file";
retrofit = new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.build();
API api = retrofit.create(API.class);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData(FILE, NAME, requestBody);
Call<JsonResponse> call = api.uploadFile(NAME, FOLDER, part);
call.enqueue(new Callback<JsonResponse>() {
@Override
public void onResponse(Call<JsonResponse> call, Response<JsonResponse> response) {
//response.body() null
//response.code() 500
//https://github.com/square/retrofit/issues/1321
Converter<ResponseBody, JsonResponse> errorConverter
= retrofit.responseBodyConverter(JsonResponse.class, new Annotation[0]);
try {
JsonResponse jsonResponse = errorConverter.convert(response.errorBody());
Log.e("error", "id:" + jsonResponse.id); //1
Log.e("error", "message:" + jsonResponse.message); //An error has occurred
Log.e("error", "path:" + jsonResponse.path); //null
} catch (IOException ignored) {
}
}
@Override
public void onFailure(Call<JsonResponse> call, Throwable t) {
}
});
}
これらのサーバーの問題のためにフィールドにエラーがあります
サービス定義が間違っているようです。試して
@Multipart
@POST("jobDocuments/upload")
Call<ResponseBody> upload(@Part("file") MultipartBody.Part file,@Part("folder") RequestBody folder,@Part("name") RequestBody name);
そして
RequestBody folder =
RequestBody.create(
MediaType.parse("multipart/form-data"), "LeadDocuments");
RequestBody name =
RequestBody.create(
MediaType.parse("multipart/form-data"), filename);
@Backgroundメソッドで。これはすべて、Retrofit2を使用していることを前提としています。