Android向服务器发送图片(一)
作为一个Android菜鸟,花了好久时间才搞定的发送图片功能,特在此写下,希望对后者有帮助。先说说我的思路:在Android通过相册选择图片,然后利用Base64对图片进行编码,再用json对图片编码和图片名进行打包发送。
-
Android端
由于篇幅限制,有关相册的部分内容参考郭霖的《第一行代码》
没有的可以私我。
接下来就上代码了建议使用google的json解析库,在build.gradle添加如下代码:
implementation 'com.google.code.gson:gson:2.8.5'
- Image.class(工具类)
public class Image {
String image,imagename;
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getImagename() {
return imagename;
}
public void setImagename(String imagename) {
this.imagename = imagename;
}
}
- Base64Util.class
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class Base64Util {
//回收图片所占的内存
public static void gcBitmap(Bitmap bitmap) {
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle(); // 回收图片所占的内存
bitmap = null;
System.gc(); // 提醒系统及时回收
}
}
/**
*
* @Title: bitmapToBase64
* @Description: TODO(Bitmap 转换为字符串)
* @param @param bitmap
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
//图片编码
@SuppressLint("NewApi")
public static String bitmapToBase64(Bitmap bitmap) {
// 要返回的字符串
String reslut = null;
ByteArrayOutputStream baos = null;
try {
if (bitmap != null) {
baos = new ByteArrayOutputStream();
/**
* 压缩只对保存有效果bitmap还是原来的大小
*/
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, baos);
baos.flush();
// 转换为字节数组
byte[] byteArray = baos.toByteArray();
// 转换为字符串
reslut = Base64.encodeToString(byteArray, Base64.DEFAULT);
baos.close();
} else {
return null;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return reslut;
}
/**
*
* @Title: base64ToBitmap
* @Description: TODO(base64l转换为Bitmap)
* @param @param base64String
* @param @return 设定文件
* @return Bitmap 返回类型
* @throws
*/
//编码转为图片
public static Bitmap base64ToBitmap(String base64String){
byte[] decode = Base64.decode(base64String, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);
return bitmap;
}
}
- HttpUtil.class(上传工具类)
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
public class HttpUtil {
//用于解析字符串
public static String doJsonPost(URL url, String jsonstr) {
HttpURLConnection urlConnection = null;
System.out.println("tag"+"这只从客户端得到的数据"+jsonstr);
try {
urlConnection = (HttpURLConnection) url.openConnection();//打开http连接
urlConnection.setConnectTimeout(8000);//连接的超时时间
urlConnection.setUseCaches(false);//不使用缓存
//urlConnection.setFollowRedirects(false);是static函数,作用于所有的URLConnection对象。
urlConnection.setInstanceFollowRedirects(true);//是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
urlConnection.setReadTimeout(8000);//响应的超时时间
urlConnection.setDoInput(true);//设置这个连接是否可以写入数据
urlConnection.setDoOutput(true);//设置这个连接是否可以输出数据
urlConnection.setRequestMethod("POST" );//设置请求的方式
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");//设置消息的类型
urlConnection.connect();// 连接,从上述至此的配置必须要在connect之前完成,实际上它只是建立了一个与服务器的TCP连接
OutputStream out = urlConnection.getOutputStream();//输出流,用来发送请求,http请求实际上直到这个函数里面才正式发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));//创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流
bw.write(jsonstr);//把json字符串写入缓冲区中
bw.flush();//刷新缓冲区,把数据发送出去,这步很重要
out.close();
bw.close();//使用完关闭
if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){//得到服务端的返回码是否连接成功
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
response.append(line);
}
return response.toString();
}
}catch (Exception e) {
}finally{
urlConnection.disconnect();//使用完关闭TCP连接,释放资源
}
return null;
}
}
- CameraActivity.class
这个类只给出上传部分的逻辑代码,关于相机和相册的部分操作可参考《第一行代码》,毕竟笔者也是学习郭霖大佬的。
public class CameraActivity extends AppCompatActivity {
".......此处省略了打开相册和相机的逻辑操作......."
"布局文件也不会给出"
//在imageview上展示图片
@RequiresApi(api = Build.VERSION_CODES.O)
private void displayImage(String imagePath){
if(imagePath!=null){
//服务器中图片servlet对应的路径
String uri="http://服务器ip:8080/Server/ImageServlet";
Bitmap bitmap=BitmapFactory.decodeFile(imagePath);
String picture=new Base64Util().bitmapToBase64(bitmap);
Image image=new Image();
image.setImage(picture);
image.setImagename("photo.jpg");
Gson gson = new Gson();
Type type = new TypeToken<Image>(){}.getType();
String jsonstr = gson.toJson(image,type);
//mtest(imagePath);
new CameraActivity.upPicture().execute(uri,jsonstr);
Log.v("上传图片","成功");
roundImageView.setImageBitmap(bitmap);
}else {
Toast.makeText(this,"failed to get image",Toast.LENGTH_SHORT).show();
}
}
//上传异步类
class upPicture extends AsyncTask<String,Integer,String>{
@Override
protected String doInBackground(String... params) {
String par = params[0];//url
String picturejson = params[1];//string
java.net.URL url = null;
try {
url = new URL(par);
} catch (MalformedURLException e) {
e.printStackTrace();
}
String result = HttpUtil.doJsonPost(url,picturejson);
return result;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
int i = Integer.parseInt(result);
if(i==1){
Toast.makeText(getApplicationContext(),"上传成功", Toast.LENGTH_SHORT).show();
return;
}else {
if (i == -1) {
Toast.makeText(getApplicationContext(), "上传失败", Toast.LENGTH_SHORT).show();
return;
}
}
}
}
}
到此Android端差不多可以了,欢迎大佬批评指教!