如何在Volley Library中获得Inpustream作为响应?

我在应用程序中使用Volley库。

在响应监听器,我需要InputStream作为响应

我如何得到它?

Solutions Collecting From Web of "如何在Volley Library中获得Inpustream作为响应?"

好吧,正如我所说的,它太复杂了,我们需要复制BasicNetwork大量代码,然后改变一些处理请求的行为,如果通过一个特殊的请求使其不同,使用MyNetworkResponse来包装该响应,最终在定制中获取InputStream NeededInsRequest

 import android.os.SystemClock; import com.android.volley.*; import com.android.volley.toolbox.BasicNetwork; import com.android.volley.toolbox.ByteArrayPool; import com.android.volley.toolbox.HttpStack; import com.android.volley.toolbox.PoolingByteArrayOutputStream; import org.apache.http.*; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.impl.cookie.DateUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.util.Date; import java.util.HashMap; import java.util.Map; public class MyNetwork extends BasicNetwork { private static int SLOW_REQUEST_THRESHOLD_MS = 3000; private static int DEFAULT_POOL_SIZE = 4096; /** * @param httpStack HTTP stack to be used */ public MyNetwork(HttpStack httpStack) { // If a pool isn't passed in, then build a small default pool that will give us a lot of // benefit and not use too much memory. this(httpStack, new ByteArrayPool(DEFAULT_POOL_SIZE)); } /** * @param httpStack HTTP stack to be used * @param pool a buffer pool that improves GC performance in copy operations */ public MyNetwork(HttpStack httpStack, ByteArrayPool pool) { super(httpStack, pool); } @Override public NetworkResponse performRequest(Request<?> request) throws VolleyError { long requestStart = SystemClock.elapsedRealtime(); while (true) { HttpResponse httpResponse = null; byte[] responseContents = null; InputStream responseIns = null; Map<String, String> responseHeaders = new HashMap<String, String>(); try { // Gather headers. Map<String, String> headers = new HashMap<String, String>(); addCacheHeaders(headers, request.getCacheEntry()); httpResponse = mHttpStack.performRequest(request, headers); StatusLine statusLine = httpResponse.getStatusLine(); int statusCode = statusLine.getStatusCode(); responseHeaders = convertHeaders(httpResponse.getAllHeaders()); // Handle cache validation. if (statusCode == HttpStatus.SC_NOT_MODIFIED) { return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, request.getCacheEntry() == null ? null : request.getCacheEntry().data, responseHeaders, true); } // Some responses such as 204s do not have content. We must check. if (httpResponse.getEntity() != null) { // Note : only particular request needed InputStream. if (request instanceof NeededInsRequest) { responseIns = httpResponse.getEntity().getContent(); } else { responseContents = entityToBytes(httpResponse.getEntity()); } } else { // Add 0 byte response as a way of honestly representing a // no-content request. responseContents = new byte[0]; } // if the request is slow, log it. long requestLifetime = SystemClock.elapsedRealtime() - requestStart; logSlowRequests(requestLifetime, request, responseContents, statusLine); if (statusCode < 200 || statusCode > 299) { throw new IOException(); } return new MyNetworkResponse(statusCode, responseContents, responseIns, responseHeaders, false); } catch (SocketTimeoutException e) { attemptRetryOnException("socket", request, new TimeoutError()); } catch (ConnectTimeoutException e) { attemptRetryOnException("connection", request, new TimeoutError()); } catch (MalformedURLException e) { throw new RuntimeException("Bad URL " + request.getUrl(), e); } catch (IOException e) { int statusCode; NetworkResponse networkResponse = null; if (httpResponse != null) { statusCode = httpResponse.getStatusLine().getStatusCode(); } else { throw new NoConnectionError(e); } VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl()); if (responseContents != null || responseIns != null) { networkResponse = new MyNetworkResponse(statusCode, responseContents, responseIns, responseHeaders, false); if (statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN) { attemptRetryOnException("auth", request, new AuthFailureError(networkResponse)); } else { // TODO: Only throw ServerError for 5xx status codes. throw new ServerError(networkResponse); } } else { throw new NetworkError(networkResponse); } } } } /** * Logs requests that took over SLOW_REQUEST_THRESHOLD_MS to complete. */ private void logSlowRequests( long requestLifetime, Request<?> request, byte[] responseContents, StatusLine statusLine) { if (DEBUG || requestLifetime > SLOW_REQUEST_THRESHOLD_MS) { VolleyLog.d("HTTP response for request=<%s> [lifetime=%d], [size=%s], " + "[rc=%d], [retryCount=%s]", request, requestLifetime, responseContents != null ? responseContents.length : "null", statusLine.getStatusCode(), request.getRetryPolicy().getCurrentRetryCount()); } } /** * Attempts to prepare the request for a retry. If there are no more attempts remaining in the * request's retry policy, a timeout exception is thrown. * @param request The request to use. */ private static void attemptRetryOnException( String logPrefix, Request<?> request, VolleyError exception) throws VolleyError { RetryPolicy retryPolicy = request.getRetryPolicy(); int oldTimeout = request.getTimeoutMs(); try { retryPolicy.retry(exception); } catch (VolleyError e) { request.addMarker( String.format("%s-timeout-giveup [timeout=%s]", logPrefix, oldTimeout)); throw e; } request.addMarker(String.format("%s-retry [timeout=%s]", logPrefix, oldTimeout)); } private void addCacheHeaders(Map<String, String> headers, Cache.Entry entry) { // If there's no cache entry, we're done. if (entry == null) { return; } if (entry.etag != null) { headers.put("If-None-Match", entry.etag); } if (entry.serverDate > 0) { Date refTime = new Date(entry.serverDate); headers.put("If-Modified-Since", DateUtils.formatDate(refTime)); } } protected void logError(String what, String url, long start) { long now = SystemClock.elapsedRealtime(); VolleyLog.v("HTTP ERROR(%s) %d ms to fetch %s", what, (now - start), url); } /** Reads the contents of HttpEntity into a byte[]. */ private byte[] entityToBytes(HttpEntity entity) throws IOException, ServerError { PoolingByteArrayOutputStream bytes = new PoolingByteArrayOutputStream(mPool, (int) entity.getContentLength()); byte[] buffer = null; try { InputStream in = entity.getContent(); if (in == null) { throw new ServerError(); } buffer = mPool.getBuf(1024); int count; while ((count = in.read(buffer)) != -1) { bytes.write(buffer, 0, count); } return bytes.toByteArray(); } finally { try { // Close the InputStream and release the resources by "consuming the content". entity.consumeContent(); } catch (IOException e) { // This can happen if there was an exception above that left the entity in // an invalid state. VolleyLog.v("Error occured when calling consumingContent"); } mPool.returnBuf(buffer); bytes.close(); } } /** * Converts Headers[] to Map<String, String>. */ private static Map<String, String> convertHeaders(Header[] headers) { Map<String, String> result = new HashMap<String, String>(); for (Header header : headers) { result.put(header.getName(), header.getValue()); } return result; } } 

将BasicNetworkreplace为初始化它的MyNetwork

 import com.android.volley.NetworkResponse; import java.io.InputStream; import java.util.Map; public class MyNetworkResponse extends NetworkResponse { public MyNetworkResponse(int statusCode, byte[] data, InputStream ins, Map<String, String> headers, boolean notModified) { super(statusCode, data, headers, notModified); this.ins = ins; } public MyNetworkResponse(byte[] data, InputStream ins) { super(data); this.ins = ins; } public MyNetworkResponse(byte[] data, InputStream ins, Map<String, String> headers) { super(data, headers); this.ins = ins; } public final InputStream ins; } 

扩展NetworkResponse ,添加一个InputStream字段。

 import com.android.volley.NetworkResponse; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.toolbox.HttpHeaderParser; import java.io.InputStream; public class NeededInsRequest extends Request<byte[]> { private final Response.Listener<byte[]> mListener; public NeededInsRequest(int method, String url, Response.Listener<byte[]> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); // this request would never use cache. setShouldCache(false); mListener = listener; } @Override protected void deliverResponse(byte[] response) { mListener.onResponse(response); } @Override protected Response<byte[]> parseNetworkResponse(NetworkResponse response) { if (response instanceof MyNetworkResponse) { // take the InputStream here. InputStream ins = ((MyNetworkResponse) response).ins; } return Response.success(response.data, HttpHeaderParser.parseCacheHeaders(response)); } } 

执行NeededInsRequest来获得InputStream,然后做任何你想要的。

我没有testing这些代码,但我认为它可以帮助,如果有一些错误,我很高兴知道这一点。

我发表了一个评论VinceStyling的答案提供他的代码更改和示例GitHub,所以这里是: https : //github.com/georgiecasey/android-volley-inputstream-as-response

您需要的Volley编辑的相关提交在这里: https : //github.com/georgiecasey/android-volley-inputstream-as-response/commit/62d9b9132c4f66b2268e9099d418b28884c26ce5

我需要Volley中的InputStream从一个URL下载图像,以InputStream的forms获取响应,并将分段上传到另一个URL。 从那以后,我不得不使用竞争的loopj Android HTTP库,发现我的用例在那个库中更容易。 所以我切换到这个应用程序库。 如果有人想要这个代码,留下另一个评论。