【发布时间】:2018-01-31 09:00:53
【问题描述】:
我正在尝试使用Android 和Retrofit 将位图发布到服务器。
目前我知道如何发布文件,但我更喜欢直接发送位图。
这是因为用户可以从他们的设备上选择任何图像。我想在它被发送到服务器之前调整它的大小以节省带宽,最好不必加载它,调整它的大小,将它作为文件保存到本地存储然后发布文件。
有人知道如何从Retrofit 发布位图吗?
【问题讨论】:
我正在尝试使用Android 和Retrofit 将位图发布到服务器。
目前我知道如何发布文件,但我更喜欢直接发送位图。
这是因为用户可以从他们的设备上选择任何图像。我想在它被发送到服务器之前调整它的大小以节省带宽,最好不必加载它,调整它的大小,将它作为文件保存到本地存储然后发布文件。
有人知道如何从Retrofit 发布位图吗?
【问题讨论】:
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
您可以将位图转换为字节数组,然后将此字节数组发布到服务器后,您可以制作一个临时文件,例如
File file = new File(this.getCacheDir(), filename);
文件直接上传到服务器
【讨论】:
注意:在除 Main 之外的其他线程上进行此转换。 RxJava 可以帮助实现这一点,或者协程
首先将您的位图转换为文件
//create a file to write bitmap data
File f = new File(context.getCacheDir(), filename);
f.createNewFile();
//Convert bitmap to byte array
Bitmap bitmap = your bitmap;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
//write the bytes in file
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fos.write(bitmapdata);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
然后使用Multipart 创建一个请求以上传您的文件
RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), f);
MultipartBody.Part body = MultipartBody.Part.createFormData("upload", f.getName(), reqFile);
您的服务调用应如下所示
interface Service {
@Multipart
@POST("/yourEndPoint")
Call<ResponseBody> postImage(@Part MultipartBody.Part image);
}
然后调用你的 api
Service service = new Retrofit.Builder().baseUrl("yourBaseUrl").build().create(Service.class);
Call<okhttp3.ResponseBody> req = service.postImage(body);
req.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
// Do Something with response
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
//failure message
t.printStackTrace();
}
});
【讨论】:
建议通过文件上传位图/图像。图像应保存在设备存储中,然后您应该多部分发送文件。但是如果您有要求不将位图/图像存储在存储中并直接通过 Retrofit 上传,那么您可以这样做。
当您需要在应用程序或后端显示图像时。将base64转为字节,将字节转为Bitmap并显示Bitmap。
将位图转换为字节[]
public static byte[] bitmapToBytes(Bitmap photo) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
将 byte[] 转换为 Base64 字符串
public static String bytesToBase64(byte[] bytes) {
final String base64 = Base64.encodeToString(bytes, 0);
return base64;
}
将 Base64 字符串转换为字节[]
public static byte[] base64ToBytes(String base64) {
final byte[] bytes = Base64.decode(base64, 0);
return bytes;
}
将字节[]转换为位图
public static Bitmap bytesToBitmap(byte[] bytes) {
final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
return bitmap;
}
我见过有人上传这样的图片,但我个人更喜欢通过文件上传。
【讨论】: