草庐IT

android - Retrofit(2.0 beta2) 分段文件上传不起作用

coder 2023-12-08 原文

我正在使用 Square Retrofit 版本 2.0 beta2。我试着关注 this tutorial .我正在尝试将位图图像上传到服务器,但不知何故代码无法正常工作。我已经尝试使用 postman 测试我的服务器,我能够发布照片甚至能够检索它。这是我的 flask Controller 。

@app.route('/api/photo/user/<int:user_id>', methods=["POST"])
    def post_user_photo(user_id):
        app.logger.info("post_user_photo=> user_id:{}, photo: {}".format(
            user_id,
            request.files['photo'].filename,
        ))
        user = User.query.get_or_404(user_id)
        try:
            user.photo = request.files['photo'].read()
        except Exception as e:
            app.logger.exception(e)
            db.session.rollback()
            raise
        db.session.commit()
        return "", codes.no_content

我已经使用 postman 测试了我的 Controller ,这里是 postman 生成的请求。

POST /api/photo/user/5 HTTP/1.1
Host: blooming-cliffs-9672.herokuapp.com
Cache-Control: no-cache
Postman-Token: 8117fb79-4781-449d-7d22-237c49b53389
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="photo"; filename="sfsu.jpg"
Content-Type: image/jpeg


----WebKitFormBoundary7MA4YWxkTrZu0gW

我已经定义了改造服务和上传图片,这是我的 Android 代码。接口(interface)部分

  @Multipart
    @POST("/api/photo/user/{userId}")
    Call<Void> uploadUserProfilePhoto(@Path("userId") Integer userId, @Part("photo") RequestBody photo);

这里是客户端构建器部分

  public static BeamItService getService(){
        if (service == null) {
            OkHttpClient client = new OkHttpClient();
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            HttpLoggingInterceptor interceptor2 = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);

            client.interceptors().add(interceptor);
            client.interceptors().add(interceptor2);

            service =  new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build().create(BeamItService.class);
        }
        return service;
    }

这是尝试上传位图的 Android Activity 代码。

private void uploadProfilePhoto(){
        BeamItService service = BeamItServiceTransport.getService();

        MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpeg");
        byte [] data = BitmapUtility.getBitmapToBytes(((BitmapDrawable) ivProfilePhoto.getDrawable()).getBitmap());
        Log.d(TAG, String.format("Profile detals => user_id: %d, size of data: %d", 5, data.length));

        RequestBody requestBody1 = RequestBody.create(MEDIA_TYPE_PNG,
                                                    data);
        Log.d(TAG, "requestBody: " + requestBody1.toString());
        RequestBody requestBody2 = new MultipartBuilder()
                .type(MultipartBuilder.FORM)
                .addPart(Headers.of("Content-Disposition", "form-data; name=\"photo\"; filename=\"t.jpg\""),
                        requestBody1)
                .build();
        Log.d(TAG, "requestBody: " + requestBody2.toString());
//        ProfileDetails profileDetails = new DBHelper(this).fetchProfileDetails();

        Call<Void> call = service.uploadUserProfilePhoto(5, requestBody2);
        call.enqueue(new ProfilePhotoUploadCallback());
    }

    private class ProfilePhotoUploadCallback implements Callback<Void> {

        @Override
        public void onResponse(Response<Void> response, Retrofit retrofit) {
            Log.d(TAG, String.format("ProfilePhotoUploadCallback=> code: %d", response.code()));
        }

        @Override
        public void onFailure(Throwable t) {

        }
    }

但是上传失败,flask app每次都返回状态码400。我试图将断点放在 flask 应用程序中,但请求甚至没有到达那里。 这是服务器日志

2015-11-02T06:05:42.288574+00:00 heroku[router]: at=info method=POST path="/api/photo/user/5" host=blooming-cliffs-9672.herokuapp.com request_id=2cc8b6c8-f12a-4e4b-8279-cedfc39712f2 fwd="204.28.113.240" dyno=web.1 connect=1ms service=88ms status=400 bytes=347
2015-11-02T06:05:42.209347+00:00 app[web.1]: [2015-11-02 06:05:42 +0000] [11] [DEBUG] POST /api/photo/user/5

我还尝试启用 retrofit 拦截器并记录请求和响应,但我没有获得整个 POST 请求正文。这是 Android 日志。

    11-02 00:24:22.119 3904-4382/com.contactsharing.beamit D/OkHttp: --> POST /api/photo/user/5 HTTP/1.1
11-02 00:24:22.119 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Type: multipart/form-data; boundary=4031e177-0e4b-4f16-abe8-20c54e506846
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Length: 17171
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Host: blooming-cliffs-9672.herokuapp.com
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Connection: Keep-Alive
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Accept-Encoding: gzip
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: User-Agent: okhttp/2.6.0-SNAPSHOT
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: --> END POST
11-02 00:24:22.179 3904-4537/com.contactsharing.beamit I/DBHelper: Updated row: 1
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: <-- HTTP/1.1 400 BAD REQUEST (195ms)
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Connection: keep-alive
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Server: gunicorn/19.3.0
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Date: Mon, 02 Nov 2015 08:24:22 GMT
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Type: text/html
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Length: 192
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Via: 1.1 vegur
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: OkHttp-Selected-Protocol: http/1.1
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: OkHttp-Sent-Millis: 1446452662120
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: OkHttp-Received-Millis: 1446452662316
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: <-- END HTTP

请帮忙,我卡住了,无法取得任何进展。

最佳答案

您在此处嵌套了一个多部分请求正文(多部分中的多部分)。

最近实现了类似的东西,而不是使用 @Multipart@Part 你可以使用 @BodyMultipartBuilder.

@POST("/api/photo/user/{userId}")
Call<Void> uploadUserProfilePhoto(@Path("userId") Integer userId, @Body RequestBody photo);

然后不使用 MultipartBuilder.addPart(...) 使用 MultipartBuilder.addFormDataPart(name, filename, requestBody)

private void uploadProfilePhoto() {
    BeamItService service = BeamItServiceTransport.getService();

    MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpeg");
    byte [] data = BitmapUtility.getBitmapToBytes(((BitmapDrawable) ivProfilePhoto.getDrawable()).getBitmap());
    Log.d(TAG, String.format("Profile detals => user_id: %d, size of data: %d", 5, data.length));

    RequestBody requestBody1 = RequestBody.create(MEDIA_TYPE_PNG, data);
    Log.d(TAG, "requestBody: " + requestBody1.toString());
    RequestBody requestBody2 = new MultipartBuilder()
            .type(MultipartBuilder.FORM)
            .addFormDataPart("photo", "t.jpg", requestBody1)
            .build();
    Log.d(TAG, "requestBody: " + requestBody2.toString());
//  ProfileDetails profileDetails = new DBHelper(this).fetchProfileDetails();

    Call<Void> call = service.uploadUserProfilePhoto(5, requestBody2);
    call.enqueue(new ProfilePhotoUploadCallback());
}

关于android - Retrofit(2.0 beta2) 分段文件上传不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33473213/

有关android - Retrofit(2.0 beta2) 分段文件上传不起作用的更多相关文章

  1. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  2. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  3. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  4. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

  5. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  6. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  7. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  8. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  9. ruby-on-rails - 安全地显示使用回形针 gem 上传的图像 - 2

    默认情况下:回形针gem将所有附件存储在公共(public)目录中。出于安全原因,我不想将附件存储在公共(public)目录中,所以我将它们保存在应用程序根目录的uploads目录中:classPost我没有指定url选项,因为我不希望每个图像附件都有一个url。如果指定了url:那么拥有该url的任何人都可以访问该图像。这是不安全的。在user#show页面中:我想实际显示图像。如果我使用所有回形针默认设置,那么我可以这样做,因为图像将在公共(public)目录中并且图像将具有一个url:Someimage:看来,如果我将图像附件保存在公共(public)目录之外并且不指定url(同

  10. ruby - Jekyll 2.0 中的 SCSS 生成错误 - 2

    我的项目布局如下:-Project-css-import.scss-_sass/main.scssimport.scss的内容是:------@import"main.scss";我期望发生的是将main.scss导入到import.scss中,然后,import.scss将在生成的_site/目录中编译为import.css。相反,我收到以下错误Conversionerror:Therewasanerrorconverting'css/import.scss'.jekyll2.0.3|Error:InvalidCSSafter"-":expectednumberorfunction,

随机推荐