前言:
现在基本不怎么搞安卓的开发了,主要做java开发,在学习各种的框架,由于学校还有项目没搞定,打算改进一下,以前做过原生servlet单文件上传,写的也比较麻烦,大概花了一天的时间,找了一些框架,自己又加调试了一下,做了一个多文件上传,简单记录下。
安卓端:
关联下jar:
dependencies {
//网络请求相关框架
compile 'org.xutils:xutils:3.5.0'
//选择本地文件框架
compile 'com.github.LuckSiege.PictureSelector:picture_library:v2.1.1'
//加载图片
compile 'com.squareup.picasso:picasso:2.5.2'
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
主要是用到了:
//网络请求相关框架
compile ‘org.xutils:xutils:3.5.0’
//选择本地文件框架
compile ‘com.github.LuckSiege.PictureSelector:picture_library:v2.1.1’
网络框架有很多,此处就选用了xutils了。既然要从手机里选择图片,由于安卓系统各种开源,各大厂商定制原因,自己以前也试着做过从相册选择照片,但是对于机型兼容不好,这个框架主要就是用来从手机里选择照片,当然,也可以选择其他文件,感兴趣可以去他的GitHub了解下。
权限:
xutils需要在AndroidManifest.xml:
初始化下xutils:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
x.Ext.init(this);
}
}
接下来还有两个布局文件文件和一个实体类,一个自定义适配器类,一个主类直接贴代码了:
Commodity.java:
/**
* Created by Administrator on 2019/2/17.
* 商品对应实体类
*/
public class Commodity {
//唯一标,没有业务含义
private Long id;
//图片地址或者路径,1-6
private List imageAddress=new ArrayList<>();
//商品标题
private String title;
//描述内容
private String content;
//商品价格
private Double price;
//商品分类
private Integer classify;
//联系手机
private String mobile;
//QQ or weChat
private String QQ;
//发布地址
private String address;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List getImageAddress() {
return imageAddress;
}
public void setImageAddress(List imageAddress) {
this.imageAddress = imageAddress;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public Integer getClassify() {
return classify;
}
public void setClassify(Integer classify) {
this.classify = classify;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getQQ() {
return QQ;
}
public void setQQ(String QQ) {
this.QQ = QQ;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Commodity{" +
"imageAddress=" + imageAddress +
", title='" + title + '\'' +
", content='" + content + '\'' +
", price=" + price +
", classify=" + classify +
", mobile='" + mobile + '\'' +
", QQ='" + QQ + '\'' +
", address='" + address + '\'' +
'}';
}
}
CustomAdapter.java:
public class CustomAdapter extends BaseAdapter {
private List mData;
private LayoutInflater layoutInflater;
public CustomAdapter(Context context, List data) {
this.layoutInflater = LayoutInflater.from(context);
this.mData = data;
}
//适配器中数据源的个数
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//将布局文件转化为View对象
View view = layoutInflater.inflate(R.layout.listview_layout, null);
ImageView imageView =view.findViewById(R.id.listView_layout_image);
//获取相应索引的ItemBean对象
LocalMedia bean = mData.get(position);
//设置控件对应属性
Bitmap bitmap = BitmapFactory.decodeFile(bean.getPath());
imageView.setImageBitmap(bitmap);
return view;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private ImageView imageView;
private GridView gridView;
private Button upload;
private Commodity commodity;
private EditText title;
private EditText content;
private EditText price;
private Spinner classify;
private EditText mobile;
private EditText weChat;
private EditText address;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
//控件初始化
private void init() {
imageView = (ImageView) findViewById(R.id.select);
imageView.setOnClickListener(this);
upload = (Button) findViewById(R.id.upload);
upload.setOnClickListener(this);
gridView = (GridView) findViewById(R.id.gridView);
title = (EditText) findViewById(R.id.title);
content = (EditText) findViewById(R.id.content);
price = (EditText) findViewById(R.id.price);
classify = (Spinner) findViewById(R.id.classify);
mobile = (EditText) findViewById(R.id.mobile);
weChat = (EditText) findViewById(R.id.weChat);
address = (EditText) findViewById(R.id.address);
commodity = new Commodity();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case PictureConfig.CHOOSE_REQUEST:
// 图片选择结果回调
List selectList = PictureSelector.obtainMultipleResult(data);
//需要判断下
if (selectList != null) {
List imagePath = new ArrayList<>();
for (int i = 0; i < selectList.size(); i++) {
imagePath.add(selectList.get(i).getPath());
}
commodity.setImageAddress(imagePath);
gridView.setVisibility(View.VISIBLE);
gridView.setAdapter(new CustomAdapter(this, selectList));
}
break;
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.select:
select();
break;
case R.id.upload:
upload();
break;
default:
break;
}
}
/**
* 上传图片
*/
private void upload() {
final String URL = "http://192.168.0.105:8080/upload";
if (commodity.getImageAddress().size() < 1) {
showToast("至少选择一张图片!");
return;
}
String title = this.title.getText().toString();
//检查是否为空,为空返回false,取反true,不往下执行
if (!isEmpty(title)) {
showToast("标题输入不能为空,请重新输入");
return;
}
commodity.setTitle(title);
String content = this.content.getText().toString();
if (!isEmpty(content)) {
showToast("内容输入不能为空,请重新输入");
return;
}
commodity.setContent(content);
String price = this.price.getText().toString();
if (!isEmpty(price)) {
showToast("请输入价格");
return;
}
commodity.setPrice(Double.valueOf(price));
int classify = this.classify.getSelectedItemPosition();
if (classify == 0) {
showToast("请选择商品类别");
return;
}
commodity.setClassify(classify);
String mobile = this.mobile.getText().toString();
if (!isEmpty(mobile)) {
showToast("手机号不能为空,请重新输入");
return;
}
commodity.setMobile(mobile);
String QQ = this.weChat.getText().toString();
if (!isEmpty(QQ)) {
showToast("微信或者QQ不能为空,请重新输入");
return;
}
commodity.setQQ(QQ);
String address = this.address.getText().toString();
if (!isEmpty(address)) {
showToast("地址输入不能为空,请重新输入");
return;
}
commodity.setAddress(address);
RequestParams params = new RequestParams(URL);
//设置支持文件上传
params.setMultipart(true);
//设置多个图片名称
for (int i = 0; i < commodity.getImageAddress().size(); i++) {
String filePath = commodity.getImageAddress().get(i);
int end = filePath.lastIndexOf("/");
String fileName = filePath.substring(end + 1);
File file = new File(filePath);
params.addBodyParameter("pictures", file);
}
//不能直接传递对象,传递属性
params.addBodyParameter("imageAddress", commodity.getImageAddress(), null);
params.addBodyParameter("title", commodity.getTitle());
params.addBodyParameter("content", commodity.getContent());
params.addBodyParameter("price", commodity.getPrice().toString());
params.addBodyParameter("classify", commodity.getClassify().toString());
params.addBodyParameter("mobile", commodity.getMobile());
params.addBodyParameter("QQ", commodity.getQQ());
params.addBodyParameter("address", commodity.getAddress());
x.http().post(params, new Callback.CacheCallback() {
@Override
public void onSuccess(String result) {
Log.e("TAG", result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
}
@Override
public void onCancelled(CancelledException cex) {
}
@Override
public void onFinished() {
}
@Override
public boolean onCache(String result) {
return false;
}
});
}
/**
* 给出Toast提示
*
* @param content 提示内容
*/
private void showToast(String content) {
Toast.makeText(this, content, Toast.LENGTH_SHORT).show();
}
/**
* 检查字符串是否为空
*
* @param string 被判断字符串
* @return 检查结果
*/
private Boolean isEmpty(String string) {
return string != null && !string.trim().equals("");
}
//打开文件选择照片
private void select() {
// 进入相册 以下是例子:用不到的 api 可以不写
PictureSelector.create(MainActivity.this)
.openGallery(PictureMimeType.ofImage())//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()
.maxSelectNum(6)// 最大图片选择数量 int
.minSelectNum(1)// 最小选择数量 int
.imageSpanCount(4)// 每行显示个数 int
.selectionMode(PictureConfig.MULTIPLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE
.previewImage(true)// 是否可预览图片 true or false
.isZoomAnim(true)// 图片列表点击 缩放效果 默认 true
.sizeMultiplier(0.5f)// glide 加载图片大小 0~1 之间 如设置 .glideOverride()无效
.hideBottomControls(true)// 是否显示 uCrop 工具栏,默认不显示 true or false
.isGif(true)// 是否显示 gif 图片 true or false
.forResult(PictureConfig.CHOOSE_REQUEST);//结果回调 onActivityResult code
}
}
核心的就是select()从相册中选择照片和upload()上传方法,里面一些校验数据的没什么用可以去掉。
activity_main.xml
listview_layout.xml:
先来看下安卓端的效果:
服务端:
为了简便开发,服务直接就使用了springboot来开发了:
先使用idea创建一个支持web项目的springboot项目,此处就不演示了,此处使用了mybatisplus操作了下数据库,也对一些文字进行了处理,觉得比较烦就可以去掉了。。
maven关联:
commons-fileupload
commons-fileupload
1.4
commons-io
commons-io
2.6
这是两个apache文件上传的jar,一定需要。
FileUploadApplication.java:
@SpringBootApplication
@ImportResource(locations = {"classpath:dispatcher.xml"})
public class FileUploadApplication {
public static void main(String[] args) {
SpringApplication.run(FileUploadApplication.class, args);
}
}
FileUploadController.java:
@RestController
public class FileUploadController {
@Autowired
private CommodityMapper mapper;
private Logger logger = LoggerFactory.getLogger(getClass());
//Commodity不需要加注解
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(@RequestParam(value = "pictures") MultipartFile[] pictures,
Commodity commodity) {
// 判断文件是否为空
if (pictures.length > 0 && pictures != null) {
try {
//判断文件目录是否存在,否则自动生成
String innerPath = ResourceUtils.getURL("classpath:").getPath();
String targetPath = innerPath + "static/images/upload/";
File f = new File(targetPath);
if (!f.exists()) {
f.mkdirs();
}
for (int i = 0; i < pictures.length; i++) {
MultipartFile file = pictures[i];
// 文件保存路径
String filePath = targetPath + file.getOriginalFilename();
// 转存文件
file.transferTo(new File(filePath));
}
} catch (Exception e) {
e.printStackTrace();
}
}
// StringBuilder builder = new StringBuilder();
// for (int i = 0; i < commodity.getImageAddress().size(); i++) {
// String randomName= UUID.randomUUID().toString().substring(0,10);
// String filePath = commodity.getImageAddress().get(i);
// String fileName = null;
// int end = filePath.lastIndexOf(".");
// //最后一张图片,做特殊处理
// if (i == (commodity.getImageAddress().size() - 1)) {
// fileName = filePath.substring(end, filePath.length() - 1);
// //改文件名
// //当前记录id+随机生成名称
// builder.append("4"+randomName+fileName);
// break;
// }
// fileName = filePath.substring(end);
// builder.append("4"+randomName+fileName + "@");
// }
// logger.info(builder.toString());
// commodity.setImagePath(builder.toString());
return "上传成功";
}
}
dispatcher.xml: