使用 Volley 且不使用 HttpEntity 处理 POST 多部分请求

2023-12-22

这并不是一个真正的问题,但是,我想在这里分享一些我的工作代码,供您需要时参考。

据我们所知HttpEntity从 API22 开始弃用,并从 API23 开始完全删除。目前,我们无法访问Android 开发人员上的 HttpEntity 参考 http://developer.android.com/reference/org/apache/http/HttpEntity.html?is-external=true不再(404)。因此,以下是我的工作示例代码使用 Volley 且不使用 HttpEntity 的 POST 多部分请求。它正在工作,经过测试Asp.Net Web API。当然,代码也许只是一个基本示例,发布了两个现有的可绘制文件,也不是所有情况的最佳解决方案,并且不好调整。

MultipartActivity.java:

package com.example.multipartvolley;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.android.volley.NetworkResponse;
import com.android.volley.Response;
import com.android.volley.VolleyError;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;


public class MultipartActivity extends Activity {

    private final Context context = this;
    private final String twoHyphens = "--";
    private final String lineEnd = "\r\n";
    private final String boundary = "apiclient-" + System.currentTimeMillis();
    private final String mimeType = "multipart/form-data;boundary=" + boundary;
    private byte[] multipartBody;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_multipart);

        byte[] fileData1 = getFileDataFromDrawable(context, R.drawable.ic_action_android);
        byte[] fileData2 = getFileDataFromDrawable(context, R.drawable.ic_action_book);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(bos);
        try {
            // the first file
            buildPart(dos, fileData1, "ic_action_android.png");
            // the second file
            buildPart(dos, fileData2, "ic_action_book.png");
            // send multipart form data necesssary after file data
            dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
            // pass to multipart body
            multipartBody = bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }

        String url = "http://192.168.1.100/api/postfile";
        MultipartRequest multipartRequest = new MultipartRequest(url, null, mimeType, multipartBody, new Response.Listener<NetworkResponse>() {
            @Override
            public void onResponse(NetworkResponse response) {
                Toast.makeText(context, "Upload successfully!", Toast.LENGTH_SHORT).show();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(context, "Upload failed!\r\n" + error.toString(), Toast.LENGTH_SHORT).show();
            }
        });

        VolleySingleton.getInstance(context).addToRequestQueue(multipartRequest);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_multipart, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void buildPart(DataOutputStream dataOutputStream, byte[] fileData, String fileName) throws IOException {
        dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
        dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\"; filename=\""
                + fileName + "\"" + lineEnd);
        dataOutputStream.writeBytes(lineEnd);

        ByteArrayInputStream fileInputStream = new ByteArrayInputStream(fileData);
        int bytesAvailable = fileInputStream.available();

        int maxBufferSize = 1024 * 1024;
        int bufferSize = Math.min(bytesAvailable, maxBufferSize);
        byte[] buffer = new byte[bufferSize];

        // read file and write it into form...
        int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        while (bytesRead > 0) {
            dataOutputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }

        dataOutputStream.writeBytes(lineEnd);
    }

    private byte[] getFileDataFromDrawable(Context context, int id) {
        Drawable drawable = ContextCompat.getDrawable(context, id);
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 0, byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }
}

多部分请求.java:

package com.example.multipartvolley;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;

import java.util.Map;

class MultipartRequest extends Request<NetworkResponse> {
    private final Response.Listener<NetworkResponse> mListener;
    private final Response.ErrorListener mErrorListener;
    private final Map<String, String> mHeaders;
    private final String mMimeType;
    private final byte[] mMultipartBody;

    public MultipartRequest(String url, Map<String, String> headers, String mimeType, byte[] multipartBody, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
        super(Method.POST, url, errorListener);
        this.mListener = listener;
        this.mErrorListener = errorListener;
        this.mHeaders = headers;
        this.mMimeType = mimeType;
        this.mMultipartBody = multipartBody;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return (mHeaders != null) ? mHeaders : super.getHeaders();
    }

    @Override
    public String getBodyContentType() {
        return mMimeType;
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        return mMultipartBody;
    }

    @Override
    protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
        try {
            return Response.success(
                    response,
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (Exception e) {
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(NetworkResponse response) {
        mListener.onResponse(response);
    }

    @Override
    public void deliverError(VolleyError error) {
        mErrorListener.onErrorResponse(error);
    }
}

UPDATE:

文字部分请参考下面@Oscar的回答。


我重写了你的代码@RacZo和@BNK,使其更加模块化且易于使用,例如

VolleyMultipartRequest multipartRequest = new VolleyMultipartRequest(Request.Method.POST, url, new Response.Listener<NetworkResponse>() {
    @Override
    public void onResponse(NetworkResponse response) {
        String resultResponse = new String(response.data);
        // parse success output
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {                
        error.printStackTrace();
    }
}) {
    @Override
    protected Map<String, String> getParams() {
        Map<String, String> params = new HashMap<>();
        params.put("api_token", "gh659gjhvdyudo973823tt9gvjf7i6ric75r76");
        params.put("name", "Angga");
        params.put("location", "Indonesia");
        params.put("about", "UI/UX Designer");
        params.put("contact", "[email protected] /cdn-cgi/l/email-protection");
        return params;
    }

    @Override
    protected Map<String, DataPart> getByteData() {
        Map<String, DataPart> params = new HashMap<>();
        // file name could found file base or direct access from real path
        // for now just get bitmap data from ImageView
        params.put("avatar", new DataPart("file_avatar.jpg", AppHelper.getFileDataFromDrawable(getBaseContext(), mAvatarImage.getDrawable()), "image/jpeg"));
        params.put("cover", new DataPart("file_cover.jpg", AppHelper.getFileDataFromDrawable(getBaseContext(), mCoverImage.getDrawable()), "image/jpeg"));

        return params;
    }
};

VolleySingleton.getInstance(getBaseContext()).addToRequestQueue(multipartRequest);

检查完整的代码VolleyMultipartRequest at my gist https://gist.github.com/anggadarkprince/a7c536da091f4b26bb4abf2f92926594.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Volley 且不使用 HttpEntity 处理 POST 多部分请求 的相关文章

随机推荐

  • 我可以在 Protractor 框架中重用/调用 Selenium-Java 框架中的现有 API 吗?

    如果这是一个愚蠢的问题 请耐心等待 但想到了一个主意 我们有一个非常复杂的 Selenium Webdriver Java 框架 但现在我们应用程序的某些部分正在 AngularJS 中实现 我们想使用量角器进行自动化测试 但我们希望重用现
  • 使用 AngularJS 启用/禁用锚标记

    如何使用指令方法启用 禁用锚标记 例子 单击编辑链接时 需要禁用或灰显创建和删除 单击创建链接时 需要禁用或灰显编辑和删除 JavaScript angular module ngApp controller ngCtrl scope fu
  • 在Android中检测蓝牙Le设备

    我是 Android 应用程序开发的初学者 我尝试阅读文档 但一无所获 Android 教程中的功能 例如StartLeScan 已被弃用 等等 是否有一个简单的函数可以返回蓝牙设备列表 就像是getDevices gt 设备列表 谢谢 基
  • 在 Ruby on Rails 中进行测试时更改规范中会话变量的值。(使用水豚和 selenium)

    我目前正在为我的 Ruby on Rails 应用程序编写规范 使用 Rspec 和 capybara 以及 selenium 来驱动浏览器 在执行其中一项规范时 我想更改会话变量的值 例如 我想设置session location US
  • 数组,如何仅显示“变化的值”

    假设我有一个包含日期和季节的数组 每天都有一个条目 我想仅在季节值发生变化时打印数组行 数组看起来像这样 2009 10 28 00 00 00 good season 2009 10 29 00 00 00 good season 200
  • 功能性香蕉旅行者 - 将行为与游戏状态结合在一起

    问题是我不知道如何创建类型的行为Behavior t GameState 我有更多代码 但我试图仅展示我认为讨论该问题所必需的内容 如果有空白需要填写 请告诉我 这是我所拥有的 data GameState GameState agent
  • 如何自定义 Android BLE(低功耗蓝牙)gatt 传输速度?

    我正在构建一个使用 BLE 技术传输图像的应用程序 图像不需要立即传输 因此在阅读一些文档后 我得出结论 1 3 Mbit s 是一个合理的选择 From Wikipedia Distance Range lt 100 m lt 330 f
  • php 文件上传时间创建

    我知道有一种方法可以使用 PHP 获取文件夹中的文件名列表 but 目前有什么方法可以获取使用 php 上传 创建文件的日期 时间吗 Unix 不跟踪文件的创建时间 只跟踪文件的更改 修改和访问时间 您可以使用文件时间 https www
  • 从命令行参数打开文件

    我正在尝试创建一个汇编程序 该程序创建在命令行 argv 1 上指定的文件 如果字符串已经存储在其中 它工作得很好 但是如果我按原样运行它 而 file name 没有移动到 rbx 它工作得很好 section text global s
  • dynamodb.put().promise() 不返回 put 对象

    我正在尝试利用 aws 和 dynamo db 的异步 等待功能 下面是如何在 async wait 之前放置对象的示例 正 如您在回调中看到的 您可以访问包含放置对象的数据 然而 在使用 async 和 Promise 的第二个代码块中
  • 编码 Katas 用于练习重构遗留代码

    近几个月来 我对 katas 编码非常感兴趣 我相信它们是磨练我的编程技能和提高我在工作中编写的代码质量的好方法 有很多地方都可以找到卡塔斯 喜欢 http codekata pragprog com http codekata pragp
  • 如何将宽字符串文字与 PRId32、PRIu64 等连接?

    假设我需要打印一个格式化的字符串int32 t使用 printf 格式说明符
  • java中new String[]{}和new String[]的区别

    I am fresher在java中 我对java有疑问 那是 String array new String 有什么用 here 有什么区别String array new String and String array new Stri
  • 模糊图像的特定部分(矩形、圆形)?

    我想模糊矩形或圆形图像 经过谷歌搜索后 我发现模糊整个图像很容易 但很难模糊图像的特定部分 矩形 圆形 那么怎么可能呢 提前致谢 只需设置你的UIImageView属性名称为 imageView 并在实现文件中以相同的顺序添加以下四个方法
  • ggvis 交互式图形无法按预期使用反应值工作

    我对以下示例有问题ggvis代码的目的是制作一个绘图 当您将鼠标悬停在该组的任何成员上时 突出显示整个点组 然后 我希望突出显示在您将鼠标悬停后立即消失 发生的情况是 突出显示最初起作用 但当您将鼠标悬停时 突出显示会保留下来 并且只有当您
  • 当填充大型可观察数组时,我可以加快淘汰速度吗?

    我有一个 Web 应用程序 它对某些数据执行 SOAP 请求 并使用结果填充淘汰视图模型 我目前收到了大约 1000 个订单项 必须将它们推送到我的淘汰视图模型上 在 Chrome 中对页面进行分析表明 大部分加载时间 CPU 都花费在 K
  • .htaccess 重定向到 HTTPS(子域除外)

    我想将所有非 https 请求重定向到 https 接受对子域的请求 例如 http example com gt https example com http example com page gt https example com p
  • Laravel:如何使用查询生成器添加 where 子句?

    我有这个查询 使用 Laravel 查询生成器进行 rows DB table elements gt where type 1 对应于 SELECT from elements WHERE type 1 现在 在某些情况下 我需要添加第二
  • iMacros 等待页面加载

    我过去一直使用 iMacros 让宏等待页面加载非常简单 设置 等待页面完成 是然而现在这不起作用 从 iMacros 网站看来http wiki imacros net 等待页面完成 http wiki imacros net WAITP
  • 使用 Volley 且不使用 HttpEntity 处理 POST 多部分请求

    这并不是一个真正的问题 但是 我想在这里分享一些我的工作代码 供您需要时参考 据我们所知HttpEntity从 API22 开始弃用 并从 API23 开始完全删除 目前 我们无法访问Android 开发人员上的 HttpEntity 参考