我正在尝试使用Retrofit 2.0对服务器进行HTTP POST
MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/plain");
MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG,90,byteArrayOutputStream);
profilePictureByte = byteArrayOutputStream.toByteArray();
Call<APIResults> call = ServiceAPI.updateProfile(
RequestBody.create(MEDIA_TYPE_TEXT, emailString),
RequestBody.create(MEDIA_TYPE_IMAGE, profilePictureByte));
call.enqueue();
Run Code Online (Sandbox Code Playgroud)
服务器返回错误,指出文件无效.
这很奇怪,因为我试图在iOS上使用相同的格式上传相同的文件(使用其他库),但它上传成功.
我想知道使用Retrofit 2.0上传图像的正确方法是什么?
在上传之前我应该先将它保存到磁盘吗?
谢谢!
PS:我已经将改造用于其他不包含图像的Multipart请求,并且已成功完成.问题是当我试图在主体中包含一个字节时.
使用Retrofit 2.0.1,我在Android App中定义的API接口中有一个调用函数:
@Multipart
@POST("api.php")
Call<ResponseBody> doAPI(
@Part("lang") String lang,
@Part("file\"; filename=\"image.jpg") RequestBody file
);
Run Code Online (Sandbox Code Playgroud)
我发送这样的请求:
Call call = service.doAPI("eng",imageFile);
其中imageFile是一个RequestBody与创建File对象.上传图片部分没有问题,而@Part("lang") String lang部分在服务器中得到额外的报价.
在PHP方面,它写如下:
$lang = trim($_POST['lang']);
Run Code Online (Sandbox Code Playgroud)
返回"eng".为什么在字符串周围有一个额外的双引号?
当然我可以删除尾随和引导双引号,但这样做很奇怪
我必须以这种格式发送一个帖子请求.
--__X_PAW_BOUNDARY__
Content-Disposition: form-data; name="user_photo[image]"; filename="file.jpg"
Content-Type: image/jpeg
ÿØÿàJFIFHHÿáLExifMM*i
ÿí8Photoshop 3.08BIM8BIM%ÔÙ²é ìøB~ÿÀ
"ÿÄ
ÿĵ}!1AQa"q2¡#B±ÁRÑð$3br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ
ÿĵw!1AQaq"2B¡±Á #3RðbrÑ
$4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÛC ÿÛC ÿÝZÿÚ?ü_¢+þæð¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¢(¯ë3þ
Run Code Online (Sandbox Code Playgroud)
我基本上试图在邮件请求中发送一张照片,其名称user_photo[image]如下图所示:
以下是我考虑过的解决方案的片段:
Call<models.UploadResponse> uploadPhoto(@Path("id") int userId, @Part MultipartBody.Part file);
MultipartBody.Part body = MultipartBody.Part.createFormData("user_photo[image]", file.getName(), requestFile);
Call<models.UploadResponse> call = userRequest.uploadPhoto(62, body);
RequestBody requestFile =
RequestBody.create(MediaType.parse("image/*"), FileUtils.getFile(PhotoUploadActivity.this, fileUri));
Call<models.UploadResponse> call = userRequest.uploadPhoto(62, requestFile);
Call<models.UploadResponse> uploadPhoto(@Path("id") int userId, @Part ("name=\"user_photo[image]\"") RequestBody file);
@Multipart
@POST("users/{id}/user_photos")
Call<models.UploadResponse> uploadPhoto(@Path("id") int userId, @Part("name=\"user_photo[image]\"") RequestBody file);
Run Code Online (Sandbox Code Playgroud)
这是okhttp日志:
D/OkHttp: Content-Type: multipart/form-data; boundary=75e8ae2e-a160-413f-82d1-3afd94f22c43
D/OkHttp: Content-Length: 43706
D/OkHttp: ??????JFIF?????????????????Photoshop …Run Code Online (Sandbox Code Playgroud) 我最近从使用 Retrofit 1.9 转向使用 Retrofit 2,并且在发布二进制数据时遇到问题。
当我使用 Retrofit 1.9 时,我能够发送一个TypedByteArray包含byte[]数据@Body的请求。最接近的等价物TypedByteArray似乎是RequestBody,我使用如下:
final ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 5, byteOutputStream);
final byte[] thumbnailBytes = byteOutputStream.toByteArray();
final RequestBody thumbnailRequestBody = RequestBody.create(MediaType.parse("image/jpeg"), thumbnailBytes);
Run Code Online (Sandbox Code Playgroud)
生成请求的代码如下:
Headers("Content-Type: image/jpeg")
@POST("/thumbnail")
Call<Void> uploadThumbnail(@Body RequestBody thumbnailContent);
Run Code Online (Sandbox Code Playgroud)
但是,似乎 Retrofit 可能试图将 解析RequestBody为 JSON 对象,因为实际发送到服务器的数据是{}.
任何有关如何正确发布二进制数据的建议或指导将不胜感激。谢谢。
我正在使用MultiPartRequester类将多部分图像上传到服务器,但我发现某些部分已弃用.例如HttpConnectionParams,getConnectionManager()等等所以任何人都有新的解决方案,不推荐使用新的API级别进行文件上传?
我正在使用此代码.
public class MultiPartRequester {
private Map<String, String> map;
private AsyncTaskCompleteListener mAsynclistener;
private int serviceCode;
private HttpClient httpclient;
private Activity activity;
private AsyncHttpRequest request;
private static final String TAG = "MultiPartRequester";
public MultiPartRequester(Activity activity, Map<String, String> map,
int serviceCode, AsyncTaskCompleteListener asyncTaskCompleteListener) {
this.map = map;
this.serviceCode = serviceCode;
this.activity = activity;
}
class AsyncHttpRequest extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... urls) {
map.remove("url");
try {
HttpPost httppost = new HttpPost(urls[0]);
httpclient = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(
httpclient.getParams(), …Run Code Online (Sandbox Code Playgroud)