美文网首页Android经验和架构Android开发Android知识
Retrofit2.0上传多张图片,PHP接收图片(包含前后端代

Retrofit2.0上传多张图片,PHP接收图片(包含前后端代

作者: alexis_zyp | 来源:发表于2017-04-25 10:09 被阅读395次
    Kapture 2017-04-25 at 10.55.gif

    1.先列出Android端使用的library:

    
    dependencies {
        ...
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:appcompat-v7:23.1.0'
        compile 'com.jakewharton:butterknife:7.0.1'
        compile 'com.squareup:otto:1.3.5'
        compile 'cn.finalteam:galleryfinal:1.4.8.4'
        compile 'com.github.bumptech.glide:glide:3.6.1'
        compile 'com.jcodecraeer:xrecyclerview:1.2.6'
        compile 'com.baoyz.actionsheet:library:1.1.5'
        compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
        compile 'org.xutils:xutils:3.1.22'
        compile 'io.reactivex:rxjava:1.0.6'
        compile 'io.reactivex:rxandroid:0.23.0'
        compile files('libs/fastjson-1.2.7.jar')
        compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
        compile 'com.squareup.retrofit2:converter-gson:2.2.0'
        compile 'com.squareup.retrofit2:adapter-rxjava:2.2.0'
        compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
        ...
       
    }
    

    Android端代码:

    public interface ApiService {
    
        /**上传单张及多张图片与文本*/
        @Multipart
        @POST("/PHP/uploads.php")
        Observable<Message> updateImages(@PartMap() Map<String, RequestBody> maps);
    
        /**上传单张及多张图片与文本*/
        @Multipart
        @POST("/PHP/uploads.php")
        Observable<Message> updateImages(@Part("filename") String description, @PartMap() Map<String, RequestBody> maps);
    
    
        /**上传单张及多张图片与文本*/
        @Multipart
        @POST("/PHP/uploads.php")
        Observable<Message> updateImages2(@Part MultipartBody.Part[] parts);
    
        /**上传单张及多张图片与文本*/
        @Multipart
        @POST("/PHP/uploads.php")
        Observable<Message> updateImages2(@Part("description") RequestBody description, @Part("key") String value  ,@Part MultipartBody.Part[] parts);
    
        /**上传单张图片*/
        @Multipart
        @POST("/PHP/uploads.php")
        Observable<Message> updateImage(
                @QueryMap Map<String, String> usermaps,
                @Part("avatar\"; filename=\"avatar.jpg") RequestBody avatar);
    
    
    public class Client {
    
        public static String API_URL = Constant.API_URL;
    
        public static ExecutorService mExecutorService;
    
        private static ApiService instance;
    
        public static ApiService getServiceClient() {
            if (instance == null) {
                synchronized (Client.class) {
                    okhttp3.OkHttpClient okHttpClient = new okhttp3.OkHttpClient.Builder()
    //                            .addNetworkInterceptor(
    //                                    new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
    //                            .cookieJar(new NovateCookieManger(context))
    //                            .cache(cache)
                                .addInterceptor(new ApiHeaders())
    //                            .addInterceptor(new CaheInterceptor(context))
    //                            .addNetworkInterceptor(new CaheInterceptor(context))
                                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                                .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                                .connectionPool(new ConnectionPool(8, 15, TimeUnit.SECONDS))
                                // 这里你可以根据自己的机型设置同时连接的个数和时间,我这里8个,和每个保持时间为10s
                                .build();
                        Retrofit retrofit = new Retrofit.Builder()
                                .client(okHttpClient)
                                .addConverterFactory(GsonConverterFactory.create())
                                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                                .baseUrl(API_URL)
                                .build();
    
                        mExecutorService = Executors.newCachedThreadPool();
                        instance = retrofit.create(ApiService.class);
                    }
                }
            }
            return instance;
        }
    
        public static void stopAll() {
            List<Runnable> pendingAndOngoing = mExecutorService.shutdownNow();
        }
    
        static class ApiHeaders implements Interceptor {
    
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Request.Builder builder = request.newBuilder();
                builder.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                        .addHeader("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.1.1; zh-cn; HTC One X - 4.1.1 - API 16 - 720x1280 Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30")
                        .addHeader("Accept-Encoding", "gzip")
                        .addHeader("Accept", "*/*")
                        .addHeader("Accept-Language", "zh-cn,zh")
                        .addHeader("Authorization", "");
    
                Request newRequest = builder.build();
    
                return chain.proceed(newRequest);
            }
    
        }
    

    上传关键代码:

        public void uploadFiles(List<String> paths) {
    //        retrofit1 的上传
    //        MultipartTypedOutput multipartTypedOutput = new MultipartTypedOutput();
    //        for (String imgPath : paths){
    //            multipartTypedOutput.addPart("uploadfile[]", new TypedFile("image/*", new File(imgPath)));
    //        }
    //        mApi.uploadFiles(multipartTypedOutput)
    //                .subscribeOn(Schedulers.computation())
    //                .subscribe(response -> handleUploadFile(response), error -> handleFailure(error));
    
            if (true) { //retrofit2第一种@PartMap() Map<String, RequestBody>方式上传多张图片
    
                HashMap<String, RequestBody> map = new HashMap<>();
                MultipartBody.Part[] parts = new MultipartBody.Part[paths.size()];
                for (String imgPath : paths) {
                    final File file = new File(imgPath);
                    map.put("uploadfile[]\"; filename=\"" + file.getName(), RequestBody.create(MediaType.parse("image/*"), file));
                }
                // create a map of data to pass along
                RequestBody tokenBody = RequestBody.create(
                        MediaType.parse("multipart/form-data"), "xxxx");
                map.put("token", tokenBody);
    //实测,zyp传过去的值有引号"zyp",所以要用body传值
    //            mApi.updateImages(map)
                mApi.updateImages("zyp",map)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(response -> handleUploadFile(response), error -> handleFailure(error));
    
            } else {//第二种MultipartBody.Part[]方式上传多张图片
    
                MultipartBody.Part[] parts = new MultipartBody.Part[paths.size()];
                int cnt = 0;
                for (String imgPath : paths) {
                    final File file = new File(imgPath);
                    RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
                    MultipartBody.Part filePart = MultipartBody.Part.createFormData("uploadfile[]", file.getName(), requestFile);
                    parts[cnt] = filePart;
                    cnt++;
                }
    
                // create a map of data to pass along
                RequestBody body = RequestBody.create(
                        MediaType.parse("multipart/form-data"), "xxxx");
    
    //            mApi.updateImages2(parts)
                //实测,value传过去的值有引号"value",所以要用body传值
                mApi.updateImages2(body,"value", parts)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(response -> handleUploadFile(response), error -> handleFailure(error));
    
            }
    //        //okhttp上传图片
    //        RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
    //                .addFormDataPart("name", "zyp")
    //                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/*"), file))
    //                .build();
    
    
        }
    
    
        private void handleUploadFile(Message message) {
    
    
            //otto事件传递
            mBus.post(message);
    
        }
    
    //接收事件代码
     @Subscribe //需要注解@Subscribe ,表明在这个函数接收数据
        public void uploadFileResponse(Message msg) {
            Log.i("@@@","uploadFileResponse: "+msg.getMessage());
            Toast.makeText(this, msg.getMessage(), Toast.LENGTH_SHORT).show();
            List<String> imgUrls = msg.getImgUrls();
            if (msg.getCode() == 1) {
                if (choosePhotoListAdapter == null) {
                    choosePhotoListAdapter = new ChoosePhotoListAdapter(this, null, imgUrls);
                    lvPhotoShow.setAdapter(choosePhotoListAdapter);
                }
                choosePhotoListAdapter.notifyDataSetChanged();
            }
        }
    
    

    Php端代码:

    //初学php,写的比较简单,不太健壮,像图片是否已经上传过,都没有判断,大家自己补充啊^_^
    
    <?php
    /**
     * Created by PhpStorm.
     * User: zhangyipeng
     * Date: 16/2/18
     * Time: 下午3:48
     */
    
    $base_path = "./upload_file/"; //接收文件目录
    $imgs = array();  //定义一个数组存放上传图片的路径
    $isSave = false;
    if (!file_exists($base_path)) {
        mkdir($base_path);
    }
    
    foreach ($_FILES["uploadfile"]["error"] as $key => $error) {
        if ($error == UPLOAD_ERR_OK) {
            $tmp_name = $_FILES["uploadfile"]["tmp_name"][$key];
            $name = $_FILES["uploadfile"]["name"][$key];
            $uploadfile = $base_path . $name;
            $isSave = move_uploaded_file($tmp_name, $uploadfile);
            if ($isSave){
                $imgs[]=$uploadfile;
            }
        }
    }
    
    if ($isSave) {
        $array = array("code" => "1", "message" =>"上传图片成功"
        , "imgUrls" => $imgs);
        echo json_encode($array);
    } else {
        $array = array("code" => "0", "message" => "上传图片失败," . $_FILES ['uploadfile'] ['error']
        , "imgUrls" => $imgs);
        echo json_encode($array);
    }
    

    其实上传多张图片成功的关键是key(uploadfile)需要带[],即uploadfile[] 。

    map.put("uploadfile[]\"; filename=\"" + file.getName(), RequestBody.create(MediaType.parse("image/*"), file));
    //下面的这种上传方式其实内部也是拼接成了"uploadfile[]\"; filename=\"" + file.getName()这个字符串
    MultipartBody.Part filePart = MultipartBody.Part.createFormData("uploadfile[]", file.getName(), requestFile);
    
    

    代码资源下载


    Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png

    补充:�PHP环境使用的是MAMP,默认文件所在目录如下,想要测试的可以看看,这里我使用了ln命令的软链接,指向到上图中得目录了,这样就不必把PHP代码放到下图目录下了,指向下就可以了,方便很多。本人对PHP了解不多,就这点小技巧,希望能帮到Android的同学。

    php.png
    1.超级简单的Android Studio jni 实现(无需命令行)
    2.让Android开发者相见恨晚的软件及插件
    3.GitHub上一些超炫的Android开源项目推荐

    相关文章

      网友评论

        本文标题:Retrofit2.0上传多张图片,PHP接收图片(包含前后端代

        本文链接:https://www.haomeiwen.com/subject/sqipzttx.html