Xutils HttpUtils上传文件的实现
来源:互联网 发布:淘宝网秋冬运动套装 编辑:程序博客网 时间:2024/06/05 20:42
今天解决了一个网络请求方面的bug, 在解决之余 熟悉了一下我们项目中网络请求用到的框架, 目前用的还是比较老的xUtils来处理http请求,闲暇之余对这部分流程进行了一番跟踪并做一下记录, 方便日后记忆学习
在理解Utils实现上传功能的流程之前, 需要对另外一个东东有所了解---HttpClient.java. 它是Apache http包里的一个类, 利用此类也可以实现上传文件的功能, 具体实现如下:
- public void upload(String localFile){
- File file = new File(localFile);
- PostMethod filePost = new PostMethod(URL_STR);
- HttpClient client = new HttpClient();
- try {
- // 通过以下方法可以模拟页面参数提交
- filePost.setParameter("userName", userName);
- filePost.setParameter("passwd", passwd);
- Part[] parts = { new FilePart(file.getName(), file) };
- filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
- client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
- int status = client.executeMethod(filePost);
- if (status == HttpStatus.SC_OK) {
- System.out.println("上传成功");
- } else {
- System.out.println("上传失败");
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- } finally {
- filePost.releaseConnection();
- }
- }
如上所述,通过HttpClient.executeMethod(PostMethod)的方式也可以实现上传文件的功能, 而在本文所讲的xUtils的上传功能实际上也是对HttpClient的封装, 提供统一接口,不必书写冗长的代码, 并添加了缓冲,重连,断点续传等功能。
以下代码是使用xUtils实现上传的demo
- //实例化HttpUtils对象, 参数设置链接超时
- HttpUtils HTTP_UTILS = new HttpUtils(60 * 1000);
- //实例化RequestParams对象
- RequestParams requestParams = new RequestParams();
- //requestParams.setContentType("multipart/form-data");
- StringBuilder picFileName = new StringBuilder();
- picFileName.append(DeviceInfo.getInstance().getGetuiClientId())
- .append(NotifyUtil.getCurrentTime()).append(".png");
- requestParams.addBodyParameter("picFileName", picFileName.toString());
- //imageFile是File格式的对象, 将此File传递给RequestParams
- requestParams.addBodyParameter("picFile", imageFile, "image/png");
- requestParams.addBodyParameter("platform", "Android");
- String photoUrl = Config.getUploadPhotoUrl();
- //通过HTTP_UTILS来发送post请求, 并书写回调函数
- HTTP_UTILS.send(HttpMethod.POST, url, params, new com.lidroid.xutils.http.callback.RequestCallBack<String>() {
- @Override
- public void onFailure(HttpException httpException, String arg1) {
- }
- @Override
- public void onSuccess(ResponseInfo<String> responseInfo) {
- }
- });
- }
可以看到使用方法就是创建一个RequestParams与一个Url, 然后通过xUtils中的HttpUtils.send方法发送请求上传imageFile这个文件,并通过RequestCallBack这个类来回调处理返回的数据, 接下来就看一下具体流程:
首先看先HttpUtils.java
- public HttpUtils(int connTimeout, String userAgent) {
- HttpParams params = new BasicHttpParams();
- ConnManagerParams.setTimeout(params, connTimeout);
- HttpConnectionParams.setSoTimeout(params, connTimeout);
- HttpConnectionParams.setConnectionTimeout(params, connTimeout);
- if (TextUtils.isEmpty(userAgent)) {
- userAgent = OtherUtils.getUserAgent(null);
- }
- HttpProtocolParams.setUserAgent(params, userAgent);
- ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(10));
- ConnManagerParams.setMaxTotalConnections(params, 10);
- HttpConnectionParams.setTcpNoDelay(params, true);
- HttpConnectionParams.setSocketBufferSize(params, 1024 * 8);
- HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
- SchemeRegistry schemeRegistry = new SchemeRegistry();
- schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- schemeRegistry.register(new Scheme("https", DefaultSSLSocketFactory.getSocketFactory(), 443));
- <span style="color:#FF0000;">//这个是核心类,最终就是调用这个HttpClient的方法去向服务端发送请求,上传文件</span>
- httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(params, schemeRegistry), params);
- httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_RETRY_TIMES));
- httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
- @Override
- public void process(org.apache.http.HttpRequest httpRequest, HttpContext httpContext) throws org.apache.http.HttpException, IOException {
- if (!httpRequest.containsHeader(HEADER_ACCEPT_ENCODING)) {
- httpRequest.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
- }
- }
- });
- httpClient.addResponseInterceptor(new HttpResponseInterceptor() {
- @Override
- public void process(HttpResponse response, HttpContext httpContext) throws org.apache.http.HttpException, IOException {
- final HttpEntity entity = response.getEntity();
- if (entity == null) {
- return;
- }
- final Header encoding = entity.getContentEncoding();
- if (encoding != null) {
- for (HeaderElement element : encoding.getElements()) {
- if (element.getName().equalsIgnoreCase("gzip")) {
- response.setEntity(new GZipDecompressingEntity(response.getEntity()));
- return;
- }
- }
- }
- }
- });
- }
就从RequestParams.java开始说起,它有几个重载的addBodyParameter的方法
当调用requestParams.addBodyParameter("picFile", imageFile, "image/png");时 看下具体代码:
- <span style="font-size:18px;">public void addBodyParameter(String key, File file, String mimeType) {
- if (fileParams == null) {
- fileParams = new HashMap<String, ContentBody>();
- }
- fileParams.put(key, new FileBody(file, mimeType));
- }</span>
fileParams是一个内部变量,声明是 private HashMap<String, ContentBody> fileParams; 可见,当传入的参数是File时,参数被保存在fileParams这个HashMap当中。OK至此, RequestParams的初始化已经结束。 接下来就是调用HttpUtils.send的方法来像服务端发送请求
- <span style="font-size:18px;">public <T> HttpHandler<T> send(HttpRequest.HttpMethod method, String url, RequestParams params,
- RequestCallBack<T> callBack) {
- if (url == null) throw new IllegalArgumentException("url may not be null");
- HttpRequest request = new HttpRequest(method, url);
- return sendRequest(request, params, callBack);
- }</span>
- <span style="font-size:18px;">public HttpRequest(HttpMethod method, URI uri) {
- super();
- this.method = method;
- setURI(uri);
- }</span>
- <span style="font-size:18px;">private <T> HttpHandler<T> sendRequest(HttpRequest request, RequestParams params, RequestCallBack<T> callBack) {
- HttpHandler<T> handler = new HttpHandler<T>(httpClient, httpContext, responseTextCharset, callBack);
- handler.setExpiry(currentRequestExpiry);
- handler.setHttpRedirectHandler(httpRedirectHandler);
- request.setRequestParams(params, handler);
- if (params != null) {
- handler.setPriority(params.getPriority());
- }
- handler.executeOnExecutor(EXECUTOR, request);
- return handler;
- }</span>
然后调用request.setRequestParams方法, 如下
- <span style="font-size:18px;">public void setRequestParams(RequestParams param) {
- if (param != null) {
- if (uriCharset == null) {
- uriCharset = Charset.forName(param.getCharset());
- }
- List<RequestParams.HeaderItem> headerItems = param.getHeaders();
- if (headerItems != null) {
- for (RequestParams.HeaderItem headerItem : headerItems) {
- if (headerItem.overwrite) {
- this.setHeader(headerItem.header);
- } else {
- this.addHeader(headerItem.header);
- }
- }
- }
- this.addQueryStringParams(param.getQueryStringParams());
- this.setEntity(param.getEntity());
- }
- }</span>
- <span style="font-size:18px;">protected Void doInBackground(Object... params) {
- if (this.state == State.CANCELLED || params == null || params.length == 0) return null;
- if (params.length > 3) {
- fileSavePath = String.valueOf(params[1]);
- isDownloadingFile = fileSavePath != null;
- autoResume = (Boolean) params[2];
- autoRename = (Boolean) params[3];
- }
- try {
- if (this.state == State.CANCELLED) return null;
- // init request & requestUrl
- request = (HttpRequestBase) params[0];
- requestUrl = request.getURI().toString();
- if (callback != null) {
- callback.setRequestUrl(requestUrl);
- }
- this.publishProgress(UPDATE_START);
- lastUpdateTime = SystemClock.uptimeMillis();
- ResponseInfo<T> responseInfo = sendRequest(request);
- if (responseInfo != null) {
- this.publishProgress(UPDATE_SUCCESS, responseInfo);
- return null;
- }
- } catch (HttpException e) {
- this.publishProgress(UPDATE_FAILURE, e, e.getMessage());
- }
- return null;
- }
- </span>
- <span style="font-size:18px;">private ResponseInfo<T> sendRequest(HttpRequestBase request) throws HttpException {
- HttpRequestRetryHandler retryHandler = client.getHttpRequestRetryHandler();
- while (true) {
- if (autoResume && isDownloadingFile) {
- File downloadFile = new File(fileSavePath);
- long fileLen = 0;
- if (downloadFile.isFile() && downloadFile.exists()) {
- fileLen = downloadFile.length();
- }
- if (fileLen > 0) {
- request.setHeader("RANGE", "bytes=" + fileLen + "-");
- }
- }
- boolean retry = true;
- IOException exception = null;
- try {
- requestMethod = request.getMethod();
- if (HttpUtils.sHttpCache.isEnabled(requestMethod)) {
- String result = HttpUtils.sHttpCache.get(requestUrl);
- if (result != null) {
- return new ResponseInfo<T>(null, (T) result, true);
- }
- }
- ResponseInfo<T> responseInfo = null;
- if (!isCancelled()) {
- HttpResponse response = client.execute(request, context);
- responseInfo = handleResponse(response);
- }
- return responseInfo;
- } catch (UnknownHostException e) {
- exception = e;
- retry = retryHandler.retryRequest(exception, ++retriedCount, context);
- } catch (IOException e) {
- exception = e;
- retry = retryHandler.retryRequest(exception, ++retriedCount, context);
- } catch (NullPointerException e) {
- exception = new IOException(e.getMessage());
- exception.initCause(e);
- retry = retryHandler.retryRequest(exception, ++retriedCount, context);
- } catch (HttpException e) {
- throw e;
- } catch (Throwable e) {
- exception = new IOException(e.getMessage());
- exception.initCause(e);
- retry = retryHandler.retryRequest(exception, ++retriedCount, context);
- }
- if (!retry) {
- throw new HttpException(exception);
- }
- }
- }
- </span>
至此,上传流程基本结束,做一下总结吧:
1 创建并实例化HttpUtils类, 在构造方法中会实例化最核心的类DefaultHttpClient对象---此对象用来执行request,向服务端发送上传请求,并返回结果
2 创建并实例化HttpParams对象, 通过addBodyParameter方法将要上传的File传给HttpParams
3 创建并实例化HttpHandler对象, 将DefaultHttpClient的实例通过参数形式,传给HttpHandler
4 创建并实例化HttpRequest对象,在此对象中,封装好了method, url, 以及params, 然后通过HttpHandler对象来执行此request,并最终调用DefaultHttpClient来执行此request, 返回HttpResponse
- Xutils HttpUtils上传文件的实现
- Xutils HttpUtils上传文件的实现
- xutils的 httpUtils讲解
- xUtils 中 HttpUtils 的使用
- Xutils的网络请求httputils
- xUtils之HttpUtils的用法
- xUtils框架中的HttpUtils模块实现原理
- xUtils框架介绍之HttpUtils的使用
- xUtils上传文件使用表单的方式上传文件。
- 简单使用xUtils-HttpUtils
- xUtils系列之HttpUtils
- 网络下载-xUtils,HttpUtils
- Xutils之HttpUtils使用
- Xutils----httpUtils请求
- xUtils httpUtils 注解
- XUtils之HttpUtils
- Android 网络操作(其中包含xUtils的HttpUtils联网)
- HttpURLConnection、HttpClient请求网络数据、Xutils的HttpUtils 请求数据
- 传智播客168期JavaEE就业班(第五天 xml约束与解析)
- Hadoop中空间数据的存储(二)
- 【Python 笔记】神奇的匿名函数
- 如何处理大量数据并发操作
- 如何优化tomcat配置(从内存、并发、缓存4个方面)优化
- Xutils HttpUtils上传文件的实现
- 查看安卓apk源码
- java学习心得——数据展示之javabeen配置和jstl配置
- RMQ板子 求区间最大最小值
- 15 装饰着模式
- 【题解】2016 BUPT Winter Training #2
- 使用Jfinal编写的HTTP API应用脚手架项目
- [BZOJ1492][NOI2007]货币兑换Cash
- 深入理解iOS API系列(一) textField:shouldChangeCharactersInRange:replacementString: