android Volley 實現檔案上傳功能,androidvolley
Volley不解釋了吧, android 官方的一個網路請求庫.
原始碼的地址在:
git@github.com:com314159/VolleyMultiPartRequest.git
是根據
https://github.com/smanikandan14/Volley-demo
這位大神修改而來的, 但是那位大神的代碼有bug, 上傳檔案不成功.
注: 我的demo裡面還整合了okhttp, 不需要的同學不用理這個類即可
實現方法:
1.添加三個jar包,
httpcore-4.3.2.jar
httpclient-4.3.5.jar
httpmime-4.3.5.jar
2.實現MultiPartStack
package com.example.volleytest;import java.io.File;import java.io.IOException;import java.util.Map;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpDelete;import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPatch;import org.apache.http.client.methods.HttpPost;import org.apache.http.client.methods.HttpPut;import org.apache.http.client.methods.HttpUriRequest;import org.apache.http.entity.ByteArrayEntity;import org.apache.http.entity.ContentType;import org.apache.http.entity.mime.HttpMultipartMode;import org.apache.http.entity.mime.MultipartEntityBuilder;import org.apache.http.entity.mime.content.FileBody;import org.apache.http.entity.mime.content.StringBody;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.protocol.HTTP;import com.android.volley.AuthFailureError;import com.android.volley.Request;import com.android.volley.Request.Method;import com.android.volley.toolbox.HurlStack;/** * @author ZhiCheng Guo * @version 2014年10月7日 上午11:00:52 這個Stack用於上傳檔案, 如果沒有這個Stack, 則上傳檔案不成功 */public class MultiPartStack extends HurlStack {@SuppressWarnings("unused")private static final String TAG = MultiPartStack.class.getSimpleName(); private final static String HEADER_CONTENT_TYPE = "Content-Type";@Overridepublic HttpResponse performRequest(Request<?> request,Map<String, String> additionalHeaders) throws IOException, AuthFailureError {if(!(request instanceof MultiPartRequest)) {return super.performRequest(request, additionalHeaders);}else {return performMultiPartRequest(request, additionalHeaders);}} private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers) { for (String key : headers.keySet()) { httpRequest.setHeader(key, headers.get(key)); } }public HttpResponse performMultiPartRequest(Request<?> request,Map<String, String> additionalHeaders) throws IOException, AuthFailureError { HttpUriRequest httpRequest = createMultiPartRequest(request, additionalHeaders); addHeaders(httpRequest, additionalHeaders); addHeaders(httpRequest, request.getHeaders()); HttpParams httpParams = httpRequest.getParams(); int timeoutMs = request.getTimeoutMs(); // TODO: Reevaluate this connection timeout based on more wide-scale // data collection and possibly different for wifi vs. 3G. HttpConnectionParams.setConnectionTimeout(httpParams, 5000); HttpConnectionParams.setSoTimeout(httpParams, timeoutMs); /* Make a thread safe connection manager for the client */ HttpClient httpClient = new DefaultHttpClient(httpParams); return httpClient.execute(httpRequest);} static HttpUriRequest createMultiPartRequest(Request<?> request, Map<String, String> additionalHeaders) throws AuthFailureError { switch (request.getMethod()) { case Method.DEPRECATED_GET_OR_POST: { // This is the deprecated way that needs to be handled for backwards compatibility. // If the request's post body is null, then the assumption is that the request is // GET. Otherwise, it is assumed that the request is a POST. byte[] postBody = request.getBody(); if (postBody != null) { HttpPost postRequest = new HttpPost(request.getUrl()); if(request.getBodyContentType() != null) postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); HttpEntity entity; entity = new ByteArrayEntity(postBody); postRequest.setEntity(entity); return postRequest; } else { return new HttpGet(request.getUrl()); } } case Method.GET: return new HttpGet(request.getUrl()); case Method.DELETE: return new HttpDelete(request.getUrl()); case Method.POST: { HttpPost postRequest = new HttpPost(request.getUrl()); postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); setMultiPartBody(postRequest,request); return postRequest; } case Method.PUT: { HttpPut putRequest = new HttpPut(request.getUrl()); if(request.getBodyContentType() != null) putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); setMultiPartBody(putRequest,request); return putRequest; } // Added in source code of Volley libray. case Method.PATCH: { HttpPatch patchRequest = new HttpPatch(request.getUrl()); if(request.getBodyContentType() != null) patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); return patchRequest; } default: throw new IllegalStateException("Unknown request method."); } }/** * If Request is MultiPartRequest type, then set MultipartEntity in the * httpRequest object. * * @param httpRequest * @param request * @throws AuthFailureError */private static void setMultiPartBody(HttpEntityEnclosingRequestBase httpRequest,Request<?> request) throws AuthFailureError {// Return if Request is not MultiPartRequestif (!(request instanceof MultiPartRequest)) {return;}// MultipartEntity multipartEntity = new// MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);MultipartEntityBuilder builder = MultipartEntityBuilder.create();/* example for setting a HttpMultipartMode */builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);// Iterate the fileUploadsMap<String, File> fileUpload = ((MultiPartRequest) request).getFileUploads();for (Map.Entry<String, File> entry : fileUpload.entrySet()) {builder.addPart(((String) entry.getKey()), new FileBody((File) entry.getValue()));}ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);// Iterate the stringUploadsMap<String, String> stringUpload = ((MultiPartRequest) request).getStringUploads();for (Map.Entry<String, String> entry : stringUpload.entrySet()) {try {builder.addPart(((String) entry.getKey()),new StringBody((String) entry.getValue(), contentType));} catch (Exception e) {e.printStackTrace();}}httpRequest.setEntity(builder.build());}}
3. 實現MultiPartRequest, 這個介面是為了方便擴充
package com.example.volleytest;import java.io.File;import java.util.Map;/** * @author ZhiCheng Guo * @version 2014年10月7日 上午11:04:36 */public interface MultiPartRequest { public void addFileUpload(String param,File file); public void addStringUpload(String param,String content); public Map<String,File> getFileUploads(); public Map<String,String> getStringUploads(); }
/** * Copyright 2013 Mani Selvaraj * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.volleytest;import java.io.File;import java.io.UnsupportedEncodingException;import java.util.HashMap;import java.util.Map;import com.android.volley.NetworkResponse;import com.android.volley.Request;import com.android.volley.Response;import com.android.volley.Response.ErrorListener;import com.android.volley.Response.Listener;import com.android.volley.toolbox.HttpHeaderParser;/** * MultipartRequest - To handle the large file uploads. * Extended from JSONRequest. You might want to change to StringRequest based on your response type. * @author Mani Selvaraj * */public class MultiPartStringRequest extends Request<String> implements MultiPartRequest{private final Listener<String> mListener;/* To hold the parameter name and the File to upload */private Map<String,File> fileUploads = new HashMap<String,File>();/* To hold the parameter name and the string content to upload */private Map<String,String> stringUploads = new HashMap<String,String>(); /** * Creates a new request with the given method. * * @param method the request {@link Method} to use * @param url URL to fetch the string at * @param listener Listener to receive the String response * @param errorListener Error listener, or null to ignore errors */ public MultiPartStringRequest(int method, String url, Listener<String> listener, ErrorListener errorListener) { super(method, url, errorListener); mListener = listener; } public void addFileUpload(String param,File file) { fileUploads.put(param,file); } public void addStringUpload(String param,String content) { stringUploads.put(param,content); } /** * 要上傳的檔案 */ public Map<String,File> getFileUploads() { return fileUploads; } /** * 要上傳的參數 */ public Map<String,String> getStringUploads() { return stringUploads; } @Override protected Response<String> parseNetworkResponse(NetworkResponse response) { String parsed; try { parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); } catch (UnsupportedEncodingException e) { parsed = new String(response.data); } return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response)); }@Overrideprotected void deliverResponse(String response) {if(mListener != null) {mListener.onResponse(response);}}/** * 空表示不上傳 */ public String getBodyContentType() { return null; }}
3.使用方法:
/**
* 通過put來上傳檔案
* @param url
* @param files
* @param params
* @param responseListener
* @param errorListener
* @param tag
*/
public staticvoid addPutUploadFileRequest(final Stringurl,
final Map<String, File>files, final Map<String, String> params,
final Listener<String>responseListener, final ErrorListenererrorListener,
final Objecttag) {
if (null ==url || null == responseListener) {
return;
}
MultiPartStringRequest multiPartRequest =new MultiPartStringRequest(
Request.Method.PUT,url, responseListener, errorListener) {
@Override
public Map<String, File> getFileUploads() {
returnfiles;
}
@Override
public Map<String, String> getStringUploads() {
returnparams;
}
};
Log.i(TAG," volley put : uploadFile " + url );
MainApplication.getVolleyQueue().add(multiPartRequest);
}
android實現檔案上傳的功可以
我是這樣做的
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(intent, "請選擇一個要上傳的檔案"), 1);
然後選擇檔案後調用
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
String url= uri.toString();
}
}
獲得路徑,根據路徑調用
public String convertCodeAndGetText(String str_filepath) {// 轉碼\
try {
File file1 = new File(str_filepath);
file_name = file1.getName();
FileInputStream in = new FileInputStream(file1);
byte[] buffer = new byte[(int) file1.length() + 100];
int length = in.read(buffer);
load = Base64.encodeToString(buffer, 0, length,
Base64.DEFAULT);
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return load;
}
對檔案進行編碼
Volley有提供檔案上傳的方法?還是要自己去實現?
我想使用類比表單提交的方式,同時傳文本資料和檔案,有沒有例子? 查看原帖>>
採納哦