安卓开发多文件上传(客户端+服务端)

前言:
现在基本不怎么搞安卓的开发了,主要做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'
}

安卓开发多文件上传(客户端+服务端)_第1张图片
主要是用到了:
//网络请求相关框架
compile ‘org.xutils:xutils:3.5.0’
//选择本地文件框架
compile ‘com.github.LuckSiege.PictureSelector:picture_library:v2.1.1’
网络框架有很多,此处就选用了xutils了。既然要从手机里选择图片,由于安卓系统各种开源,各大厂商定制原因,自己以前也试着做过从相册选择照片,但是对于机型兼容不好,这个框架主要就是用来从手机里选择照片,当然,也可以选择其他文件,感兴趣可以去他的GitHub了解下。
权限:





xutils需要在AndroidManifest.xml:
安卓开发多文件上传(客户端+服务端)_第2张图片
初始化下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:




    

先来看下安卓端的效果:
安卓开发多文件上传(客户端+服务端)_第3张图片
安卓开发多文件上传(客户端+服务端)_第4张图片
安卓开发多文件上传(客户端+服务端)_第5张图片
服务端:
为了简便开发,服务直接就使用了springboot来开发了:
先使用idea创建一个支持web项目的springboot项目,此处就不演示了,此处使用了mybatisplus操作了下数据库,也对一些文字进行了处理,觉得比较烦就可以去掉了。。
maven关联:

    
        commons-fileupload
        commons-fileupload
        1.4
    
    
        commons-io
        commons-io
        2.6
    

这是两个apache文件上传的jar,一定需要。
安卓开发多文件上传(客户端+服务端)_第6张图片
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:



    


    







    
    
    
    



    
    




运行测试下:
安卓开发多文件上传(客户端+服务端)_第7张图片
安卓开发多文件上传(客户端+服务端)_第8张图片
封装好的实体类属性也传递过来了,此处就不再截图了,可以自己尝试下。

你可能感兴趣的:(安卓开发)