为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

汪汪一只猫 2024-01-28 17:33:14
我正在开发一个 Android 应用程序,它发布一些用户输入的数据和用户签名(使用签名板捕获签名并将其转换为 bmp 文件)。现在,在发布整个数据之前,我需要请求服务器上传我的画布签名。所以服务器将回复两个 url(参考图片 1),分别是 put url 和 get url 现在我必须使用 PUT url 上传签名图像文件,整个过程通过邮递员成功,但我无法在 Android 应用程序上实现。Put URl 的主体是二进制的,我选择一些随机图像文件。仅供参考,请参阅随附的屏幕截图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 应用程序中呢?
查看完整描述

1 回答

?
largeQ

TA贡献2039条经验 获得超7个赞

数据准备部分代码对我来说看起来不错。但是您用于 PUT 请求的 URL 是错误的。

正如你在问题中提到的

在发布整个数据之前,我需要请求服务器上传我的画布签名。所以服务器会回复两个网址

该 API 返回 2 个 URL。从这 2 个 URL 中,您选择第二个 URL 来上传文件。我希望到目前为止它在 Android 部分工作得很好。

现在,是时候上传文件了。您已从 API 获得了用于上传文件的完全限定 URL。只需将您的网址替换BASE_URL为您获得的第二个网址即可。@Path("Put_path")您应该使用注释,而不是使用@Url注释。就像下面这样,

@PUT()   /* remove "{Put_path}" parameter*/

Call<Object> aws_upload(

    @Url String path,   /* replace @Path() with @Url */

    @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);

解释


怎么运行的?

假设您想访问以下 URL


https://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);

每当你调用上面的方法时,它都会构建一个类似的 URL


https://api.example.com/users/100

从上面的示例中我们了解到@GET(),@POST()、@PUT()、@DELETE()等方法接受部分 URL,Retrofit 客户端将为您生成完全限定的 URL。


如果您想从 Retrofit 客户端访问 BASE_URL 以外的 URL,该怎么办?

在这种情况下,我们使用Retrofit的@Url注解。它将完全替换当前请求的 BASE_URL。


我将演示与上面相同的示例,但带有@Url注释。


@GET()  // notice the difference you don't need to pass partial path here

Call<UserModel> fetchUserById(@Url String url);

这次我将在调用方法或 Activity/Fragment 中硬编码完全限定的 URL。


String overrideUrl = "https://api.example.com/users/200"; // prepare fully qualified url


SomeServiceInterface service = ...


Call<UserModel> call = service.fetchUserById(overrideUrl);  // pass it to method as an argument


call.enqueue(/* callback implementation here */);


查看完整回答
反对 回复 2024-01-28
  • 1 回答
  • 0 关注
  • 35 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信