项目地址:https://github.com/jihymood/TakePicture
这篇文章讲的很好:Retrofit2文件上传
使用retrofit2+rxjava2
PointApi
public interface PointApi {
@Multipart
@POST("New_work_order/uploadFile")
Observable<ResponseObj<Boolean>> uploadFile(@PartMap Map<String, InputStream> map);
@Multipart
@POST("New_work_order/uploadFile")
Observable<ResponseObj<Boolean>> uploadFile2(@PartMap Map<String, RequestBody> files);
}
MainActivity,主要看onActivityResult方法中的,map里的key必须是file.getName() + ""; filename="" + file.getName(),这样才能在后台的方法中接收到,具体是为什么有待研究
package com.cc.csdndemo1;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.takephotoTV)
Button takephotoTV;
@BindView(R.id.savephotoTV)
Button savephotoTV;
@BindView(R.id.imageIV)
ImageView imageIV;
private final int CAMERA_REQUEST = 8888;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
@OnClick({R.id.takephotoTV, R.id.savephotoTV})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.takephotoTV:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
break;
case R.id.savephotoTV:
getFile();
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Bitmap bitmap = null;
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
bitmap = (Bitmap) data.getExtras().get("data");
imageIV.setImageBitmap(bitmap);
}
/**
* Map<String, InputStream>
* 方法一
*/
File file = compressImage(bitmap);
Map<String, InputStream> files = new HashMap<>();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
files.put(file.getName() + "\"; filename=\"" + file.getName(), inputStream);
/**
* Map<String, RequestBody>
* 方法二:map里的key必须是file.getName() + "\"; filename=\"" + file.getName()这样
* 这样才能在后台的方法中接收到,具体是为什么有待研究
*/
Map<String, RequestBody> map = new HashMap<>();
File file1 = compressImage(bitmap);
String ext = file1.getName().substring(file1.getName().lastIndexOf(".") + 1);
RequestBody requestBody = RequestBody.create(MediaType.parse("image/" + ext), file1);
map.put(file1.getName() + "\"; filename=\"" + file1.getName(), requestBody);
ApiManager.getInstance()
.pointApiService()
// .uploadPicture1(files)
// .uploadPicture2(map)
.uploadPicture(map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new io.reactivex.functions.Consumer<ResponseObj<Boolean>>() {
@Override
public void accept(ResponseObj<Boolean> booleanResponseObj) throws Exception {
Log.e("MainActivity", "booleanResponseObj:" + booleanResponseObj.data.toString());
}
}, new io.reactivex.functions.Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("MainActivity", "throwable:" + throwable);
}
});
}
/**
* 压缩图片(质量压缩)
*
* @param bitmap
*/
public File compressImage(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
//循环判断如果压缩后图片是否大于500kb,大于继续压缩;不进行压缩的话调过这段代码
// while (baos.toByteArray().length / 1024 > 500) {
// baos.reset();//重置baos即清空baos
// options -= 10;//每次都减少10
// bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
// long length = baos.toByteArray().length;
// }
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date(System.currentTimeMillis());
String filename = format.format(date);
File file = new File(Environment.getExternalStorageDirectory(), filename + ".png");
try {
FileOutputStream fos = new FileOutputStream(file);
try {
fos.write(baos.toByteArray());
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return file;
}
/**
* 选择手机指定目录文件上传到电脑
*/
public void getFile() {
FileInputStream fis = null;
FileOutputStream fos = null;
File file = null;
String name = "拍照姿势大全,50条顶级秘籍.txt";
String path = Environment.getExternalStorageDirectory().getPath() + "/" + name;
try {
file = new File(path);
fis = new FileInputStream(file);
Log.e("MainActivity", String.valueOf(fis.available()));
/**
* 方法一:如果使用InputStream传的话,会丢失大部分数据
* 测试中,一个2946kb的文件传到后台只有2kb了
*/
Map<String, InputStream> files = new HashMap<>();
files.put(name + "\"; filename=\"" + name, fis);
/**
* 方法二:使用RequestBody传的话,不会丢失数据,可以正常写到后台
*/
Map<String, RequestBody> map = new HashMap<>();
String ext = file.getName().substring(file.getName().lastIndexOf(".") + 1);
RequestBody requestBody = RequestBody.create(MediaType.parse("image/" + ext), file);
map.put(file.getName() + "\"; filename=\"" + file.getName(), requestBody);
ApiManager.getInstance()
.pointApiService()
// .uploadFile(files)
.uploadFile1(map)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<ResponseObj<Boolean>>() {
@Override
public void accept(ResponseObj<Boolean> booleanResponseObj) throws Exception {
Log.e("MainActivity", booleanResponseObj.data.toString());
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.e("MainActivity", throwable.getMessage());
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
后台部分:使用Intellij IDEA+SpringBoot开发
在control 层
package com.jspptd.postal.collectserver.restcontrol;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
/**
* Created by LOG on 2017/7/5.
*/
@RestController
@RequestMapping("/takePicture")
public class CollectController {
private Logger log = LoggerFactory.getLogger(CollectController.class);
@Value("${destDirName}")
protected String destDirName;
/**
* 文件上传
*/
@RequestMapping(value = "/uploadPicture", method = RequestMethod.POST)
ResponseObj<Boolean> uploadPicture(HttpServletRequest request) {
log.info("进入文件上传逻辑");
if (request instanceof MultipartHttpServletRequest) {
try {
MultipartHttpServletRequest mulRequest = (MultipartHttpServletRequest) request;
Set<Map.Entry<String, MultipartFile>> set = mulRequest.getFileMap().entrySet();
Map<String, InputStream> listFile = new LinkedHashMap<>();
log.info("个数" + Integer.toString(set.size()));
for (Map.Entry<String, MultipartFile> each : set) {
String fileName = each.getKey();
MultipartFile file = each.getValue();
//这里需要上传FTP
try {
listFile.put(fileName, file.getInputStream());
} catch (Exception ex) {
return new ResponseObj<>(false, new Error("文件存储失败"));
}
}
String formjson = mulRequest.getParameter("content");
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// boolean result = iInstallWorkOrder.upLoadFile(listFile);
boolean result = true;
return new ResponseObj<>(result);
} catch (Exception ex) {
return new ResponseObj<>(false, new Error(ex.getMessage()));
}
} else {
return new ResponseObj<>(false, new Error("文件上传:数据格式不正确"));
}
}
/**
* 接收到安卓端传过来的map,将图片保存到本地电脑
*/
@RequestMapping(value = "/picture", method = RequestMethod.POST)
public ResponseObj<Boolean> reportCompany(HttpServletRequest request) {
log.info("进入文件上传逻辑");
if (request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest mulRequest = (MultipartHttpServletRequest) request;
Set<Map.Entry<String, MultipartFile>> set = mulRequest.getFileMap().entrySet();
String photoId = UUID.randomUUID().toString();
for (Map.Entry<String, MultipartFile> each : set) {
String fileName = each.getKey();
String name = each.getValue().getOriginalFilename();
String suffixal = getSuffixal(name);
try {
writeToLocal(fileName, each.getValue().getInputStream());
} catch (IOException e) {
e.printStackTrace();
return new ResponseObj(false, new Error("文件保存失败"));
}
}
}
return new ResponseObj<>(true, null);
}
/**
* 接收到安卓端传过来的map,将图片保存到本地电脑
*/
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public ResponseObj<Boolean> uploadFile(HttpServletRequest request) {
log.info("进入文件上传逻辑");
if (request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest mulRequest = (MultipartHttpServletRequest) request;
Set<Map.Entry<String, MultipartFile>> set = mulRequest.getFileMap().entrySet();
String photoId = UUID.randomUUID().toString();
for (Map.Entry<String, MultipartFile> each : set) {
String fileName = each.getKey();
String name = each.getValue().getOriginalFilename();
String suffixal = getSuffixal(name);
try {
writeToLocal(fileName, each.getValue().getInputStream());
} catch (IOException e) {
e.printStackTrace();
return new ResponseObj(false, new Error("文件保存失败"));
}
}
}
return new ResponseObj<>(true, null);
}
/**
* 将InputStream写入本地文件
* 输入流
*
* @throws IOException
*/
private void writeToLocal(String fileName, InputStream input) throws IOException {
createDir(destDirName);
String dirFile = destDirName + fileName;
int len;
byte[] bytes = new byte[1024];
FileOutputStream fos = new FileOutputStream(dirFile);
while ((len = input.read(bytes)) != -1) {
fos.write(bytes, 0, len);
fos.flush();
}
fos.close();
input.close();
System.out.print("创建成功");
}
/**
* 创建文件夹
*
* @param destDirName
* @return
*/
public boolean createDir(String destDirName) {
File dir = new File(destDirName);
if (dir.exists()) {
return false;
}
if (!destDirName.endsWith(File.separator)) {
destDirName = destDirName + File.separator;
}
//创建目录
if (dir.mkdirs()) {
return true;
} else {
return false;
}
}
/**
* 截取图片后缀名
*/
public String getSuffixal(String name) {
String str = name.substring(name.length() - 4, name.length());
return str;
}
/**
* 获取当前时间
*/
public long getNowTime() {
return new Date().getTime();
}
/**
* 判断String是否为空
*
* @param string
* @return
*/
public boolean isEmpty(String string) {
return null == string || "".equals(string);
}
}


网友评论