猿问

如何使用二进制形式的 Retrofit 上传图像?

我正在开发一个 Android 应用程序,它发布一些用户输入的数据和用户签名(使用签名板捕获签名并将其转换为 bmp 文件)。

现在,在发布整个数据之前,我需要请求服务器上传我的画布签名。所以服务器将回复两个 url(参考图片 1),分别是 put url 和 get url 现在我必须使用 PUT url 上传签名图像文件,整个过程通过邮递员成功,但我无法在 Android 应用程序上实现。Put URl 的主体是二进制的,我选择一些随机图像文件。仅供参考,请参阅随附的屏幕截图

https://img1.sycdn.imooc.com/65b61f8b0001011c08110316.jpg

https://img1.sycdn.imooc.com/65b61f92000176f109260294.jpg

https://img1.sycdn.imooc.com/65b61f99000113e210450291.jpg

https://img1.sycdn.imooc.com/65b61f9f00010b8607070137.jpg

Retrofit retrofit_image_upload=new Retrofit.Builder()

                                        .baseUrl(Aws_url) // base url retrive using Uri class using uri.getAuthority and concat with "https:/"

                                        .addConverterFactory(GsonConverterFactory.create())

                                        .build();

                ByteArrayOutputStream stream=new ByteArrayOutputStream();

                signature.compress(Bitmap.CompressFormat.PNG,100,stream);

                byte[] byteArray=stream.toByteArray();

                final RequestBody requestBody=RequestBody.create(MediaType.parse("application/octet-stream"),byteArray);

现在调用api并传递数据


                                Call<Object> image_upload_call= null;

                                try {

                                    image_upload_call = final_upload.aws_upload(path,auth,requestBody.contentLength(),x_amz_acl,AWSAccessKeyId,Expires,Signature_aws,requestBody);

                                } catch (IOException e) {

                                    e.printStackTrace();

                                }

图片上传接口


    @PUT("{Put_path}")

    Call<Object> aws_upload(@Path("Put_path") String path,

                            @Header("auth") String auth,

                            @Header("Content-Length") long length,

                            @Query("x-amz-acl") String x_amz,

                            @Query("AWSAccessKeyId") String awskey,

                            @Query("Expires") String Expires,

                            @Query("Signature") String Awssignature,

                            @Body RequestBody image);

}

当我使用此代码设置服务器不接受来自 Android 应用程序的文件,响应是错误代码 403,当我尝试从邮递员软件上传图像文件时,它工作正常。那么我该如何将其实现到 Android 应用程序中呢?



汪汪一只猫
浏览 109回答 1
1回答

largeQ

数据准备部分代码对我来说看起来不错。但是您用于 PUT 请求的 URL 是错误的。正如你在问题中提到的在发布整个数据之前,我需要请求服务器上传我的画布签名。所以服务器会回复两个网址该 API 返回 2 个 URL。从这 2 个 URL 中,您选择第二个 URL 来上传文件。我希望到目前为止它在 Android 部分工作得很好。现在,是时候上传文件了。您已从 API 获得了用于上传文件的完全限定 URL。只需将您的网址替换BASE_URL为您获得的第二个网址即可。@Path("Put_path")您应该使用注释,而不是使用@Url注释。就像下面这样,@PUT()&nbsp; &nbsp;/* remove "{Put_path}" parameter*/Call<Object> aws_upload(&nbsp; &nbsp; @Url String path,&nbsp; &nbsp;/* replace @Path() with @Url */&nbsp; &nbsp; @Header("auth") String auth,&nbsp; &nbsp; @Header("Content-Length") long length,&nbsp; &nbsp; @Query("x-amz-acl") String x_amz,&nbsp; &nbsp; @Query("AWSAccessKeyId") String awskey,&nbsp; &nbsp; @Query("Expires") String Expires,&nbsp; &nbsp; @Query("Signature") String Awssignature,&nbsp; &nbsp; @Body RequestBody image);解释怎么运行的?假设您想访问以下 URLhttps://api.example.com/users/{user_id}在 Retrofit 中,您声明 aBASE_URL并为其赋值 value https://api.example.com/。在您的服务接口文件中,您声明一个如下所示的方法@GET("users/{user_id}")Call<UserModel> fetchUserById(@Path("user_id") int userId);每当你调用上面的方法时,它都会构建一个类似的 URLhttps://api.example.com/users/100从上面的示例中我们了解到@GET(),@POST()、@PUT()、@DELETE()等方法接受部分 URL,Retrofit 客户端将为您生成完全限定的 URL。如果您想从 Retrofit 客户端访问 BASE_URL 以外的 URL,该怎么办?在这种情况下,我们使用Retrofit的@Url注解。它将完全替换当前请求的 BASE_URL。我将演示与上面相同的示例,但带有@Url注释。@GET()&nbsp; // notice the difference you don't need to pass partial path hereCall<UserModel> fetchUserById(@Url String url);这次我将在调用方法或 Activity/Fragment 中硬编码完全限定的 URL。String overrideUrl = "https://api.example.com/users/200"; // prepare fully qualified urlSomeServiceInterface service = ...Call<UserModel> call = service.fetchUserById(overrideUrl);&nbsp; // pass it to method as an argumentcall.enqueue(/* callback implementation here */);
随时随地看视频慕课网APP

相关分类

Java
我要回答