美文网首页
Android Http文件上传方法和实践

Android Http文件上传方法和实践

作者: NiceDream | 来源:发表于2021-02-08 17:34 被阅读0次

    文件上传在应用中是比较常用的的一种功能,比如用户的意见反馈功能。用户可以上传图片,音视频等文件,方便用户反馈问题的情况。

    下来我将和大家一起梳理下需要掌握的知识,少走弯路一步到位,实现文件上传功能。

    第一步:了解请求头

    需要先大致了解一下上传信息需要的请求结构。当我们掌握了请求头的结构,就可以根据自己项目情况选择sdk或者自己实现HTTP请求。

    使用HTTP进行文件上传需要用到POST请求。POST请求包含请求Head 和请求Body。

    上传文件需要使用 Content-type为multipart/form-data 的格式,发送请求信息。这种格式的数据会有一个边界线用于分割不同的字段。如下文中的:boundary=86489a0c-3d1f-4351-8f49-58315690babe

    请求Head: 一般会携带客户端的一些信息包括签名,token等。服务端用这些信息来校验是否合法。

    请求Body: 会携带文件的信息和相关的参数便于服务端进行区分。

    消息头可以携带签名信息等字段,用于服务端校验。请求头中的 head1 和head2,代表token,uuid,key等信息用于校验。

    
    POST https://*****/upload
    Content-Type: multipart/form-data; boundary=86489a0c-3d1f-4351-8f49-58315690babe
    Content-Length: 83014
    head1: param
    head2: param
    
    

    消息主体以分界线开始,紧接着就是内容描述信息,可以携带多个字段进行资源数据的描述。最后是字段具体的内容(文本或二进制)。

    请求体中的param1 和param2 代表携带文件的相关参数信息,比如文件扩展名等,方便服务端进行区分

    --86489a0c-3d1f-4351-8f49-58315690babe
    Content-Disposition: form-data; name="param1"
    Content-Length: 8
    param1
    
    --86489a0c-3d1f-4351-8f49-58315690babe
    Content-Disposition: form-data; name="param2"
    Content-Length: 3
    param2
    
    --86489a0c-3d1f-4351-8f49-58315690babe
    Content-Disposition: form-data; name="file"; filename="pic.png"
    Content-Type: application/otcet-stream
    Content-Length: 82560
    *****
    
    --86489a0c-3d1f-4351-8f49-58315690babe
    
    

    消息主体以boundary结束。

    第二步:实践

    我们将用目前比较流行的框架实现上面的结构。为了方便了解,我会一一对应的结构,实现上面的Post接口,实际应用中可以充分利用框架的进行接口优化。

    方案1:直接使用OKHttp 上传文件

            File file= new File(file);
    
            // 构建okhttpclient,使用HttpLoggingInterceptor 打印调试日志
            OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
            clientBuilder.connectTimeout(Config.DEFAULT_TIMEOUT, TimeUnit.SECONDS);
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            clientBuilder.addInterceptor(loggingInterceptor);
            OkHttpClient client = clientBuilder.build();
    
    
            // 构造请求头
            Headers.Builder headerBuilder =  new Headers.Builder();
            headerBuilder.add("head1","***");
            headerBuilder.add("head2","***");
            
    
            // 构造请求体
            MultipartBody.Builder builder = new MultipartBody.Builder();
            builder.setType(MultipartBody.FORM);
            
            
            builder.addPart(
                            Headers.of("Content-Disposition", "form-data; name=\"param1\""),
                            RequestBody.create(null, "param1"));
                            
    
            builder.addPart(
                            Headers.of("Content-Disposition", "form-data; name=\"param2\""),
                            RequestBody.create(null, "param2"));
    
            MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
            RequestBody filebody = MultipartBody.create(MEDIA_TYPE_PNG, file);
            builder.addFormDataPart("file",file.getName(),filebody);
    
            MultipartBody body = builder.build();
    
            // 构造请求
            Request request = new Request.Builder()
                    .headers(headerBuilder.build())
                    .url("***********")
                    .post(body)
                    .build();
    
            // 发起请求
            Call call = client.newCall(request);
            call.enqueue(new Callback() {
    
    
                @Override
                public void onFailure(Call call, IOException e) {
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
    
                }
            });
    
    

    方案2:利用Retrofit 上传文件

    实例化Retroift 对象

            // 构造okhttp
            OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
            clientBuilder.connectTimeout(Config.DEFAULT_TIMEOUT, TimeUnit.SECONDS);
    
            // 打印网络请求日志
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            clientBuilder.addInterceptor(loggingInterceptor);
    
            mOkHttpClient = httpClientBuilder.build();
            
            // 构造Retrofit
            mRetrofit = new Retrofit.Builder()
                    .client(mOkHttpClient)
                    .baseUrl(BASE_URL)
                    // 增加 Gson转换
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
    

    定义Retrofit接口

            @Multipart
            @POST("***")
            Call<ResponseBody> uploadFile(@Header("head1") String head1,
                                      @Header("head2") String head2,
                                      @Part MultipartBody.Part param1,
                                      @Part MultipartBody.Part param2,
                                      @Part MultipartBody.Part multipartBody);
                                      
                                      
        
    

    调用Retrofit接口

            mApiService = NetworkService.getInstance().getService(Api.class);
    
            //请求体
            MultipartBody.Part param1 = MultipartBody.Part.createFormData("param1", "param1");
            MultipartBody.Part param2 = MultipartBody.Part.createFormData("param2", "param2");
    
            File file = new File("path");
            RequestBody body = RequestBody.create(MediaType.parse("application/otcet-stream"), file);
            MultipartBody.Part filebody = MultipartBody.Part.createFormData("file",file.getName(),body);
    
            call = mApiService.uploadFile("head1","head2",param1,param2,filebody);
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, 
    
                }
    
                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
    
                }
            });
    

    调试工具

    对于在家没有后端支持的同学,可以使用 Http File Server 在局域网类部署服务端,然后进行接口测试。
    Http File Server 工具可以在百度上搜到,使用的中可以关闭用户校验功能。

    相关文章

      网友评论

          本文标题:Android Http文件上传方法和实践

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