国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

android中okhttp實現斷點上傳示例

2019-12-12 03:44:05
字體:
來源:轉載
供稿:網友

前言

之前項目需要上傳大文件的功能,上傳大文件經常遇到上傳一半由于網絡或者其他一些原因上傳失敗。然后又得重新上傳(很麻煩),所以就想能不能做個斷點上傳的功能。于是網上搜索,發現市面上很少有斷點上傳的案例,有找到一個案例也是采用SOCKET作為上傳方式(大文件上傳,不適合使用POST,GET形式)。由于大文件夾不適合http上傳的方式,所以就想能不能把大文件切割成n塊小文件,然后上傳這些小文件,所有小文件全部上傳成功后再在服務器上進行拼接。這樣不就可以實現斷點上傳,又解決了http不適合上傳大文件的難題了嗎!!!

原理分析

Android客戶端

首先,android端調用服務器接口1,參數為filename(服務器標識判斷是否上傳過)

如果存在filename,說明之前上傳過,則續傳;如果沒有,則從零開始上傳。

然后,android端調用服務器接口2,傳入參數name,chunck(傳到第幾塊),chuncks(總共多少塊)

 

服務器端

接口一:根據上傳文件名稱filename 判斷是否之前上傳過,沒有則返回客戶端chunck=1,有則讀取記錄chunck并返回。

接口二:上傳文件,如果上傳塊數chunck=chuncks,遍歷所有塊文件拼接成一個完整文件。

 服務端源代碼

服務器接口1

@WebServlet(urlPatterns = { "/ckeckFileServlet" })public class CkeckFileServlet extends HttpServlet {  private FileUploadStatusServiceI statusService;  String repositoryPath;  String uploadPath;  @Override  public void init(ServletConfig config) throws ServletException {    ServletContext servletContext = config.getServletContext();    WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);    statusService = (FileUploadStatusServiceI) context.getBean("fileUploadStatusServiceImpl");    repositoryPath = FileUtils.getTempDirectoryPath();    uploadPath = config.getServletContext().getRealPath("datas/uploader");    File up = new File(uploadPath);    if (!up.exists()) {      up.mkdir();    }  }  @Override  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {    // TODO Auto-generated method stub    String fileName = new String(req.getParameter("filename"));    //String chunk = req.getParameter("chunk");    //System.out.println(chunk);    System.out.println(fileName);    resp.setContentType("text/json; charset=utf-8");    TfileUploadStatus file = statusService.get(fileName);    try {      if (file != null) {        int schunk = file.getChunk();        deleteFile(uploadPath + schunk + "_" + fileName);        //long off = schunk * Long.parseLong(chunkSize);        resp.getWriter().write("{/"off/":" + schunk + "}");      } else {        resp.getWriter().write("{/"off/":1}");      }    } catch (Exception e) {      // TODO Auto-generated catch block      e.printStackTrace();    }  }}

服務器接口2

@WebServlet(urlPatterns = { "/uploaderWithContinuinglyTransferring" })public class UploaderServletWithContinuinglyTransferring extends HttpServlet {  private static final long serialVersionUID = 1L;  private FileUploadStatusServiceI statusService;  String repositoryPath;  String uploadPath;  @Override  public void init(ServletConfig config) throws ServletException {    ServletContext servletContext = config.getServletContext();    WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);    statusService = (FileUploadStatusServiceI) context.getBean("fileUploadStatusServiceImpl");    repositoryPath = FileUtils.getTempDirectoryPath();    System.out.println("臨時目錄:" + repositoryPath);    uploadPath = config.getServletContext().getRealPath("datas/uploader");    System.out.println("目錄:" + uploadPath);    File up = new File(uploadPath);    if (!up.exists()) {      up.mkdir();    }  }  @SuppressWarnings("unchecked")  public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    response.setCharacterEncoding("UTF-8");    Integer schunk = null;// 分割塊數    Integer schunks = null;// 總分割數    String name = null;// 文件名    BufferedOutputStream outputStream = null;    if (ServletFileUpload.isMultipartContent(request)) {      try {        DiskFileItemFactory factory = new DiskFileItemFactory();        factory.setSizeThreshold(1024);        factory.setRepository(new File(repositoryPath));// 設置臨時目錄        ServletFileUpload upload = new ServletFileUpload(factory);        upload.setHeaderEncoding("UTF-8");        upload.setSizeMax(5 * 1024 * 1024 * 1024);// 設置附近大小        List<FileItem> items = upload.parseRequest(request);        // 生成新文件名        String newFileName = null;         for (FileItem item : items) {          if (!item.isFormField()) {// 如果是文件類型            name = newFileName;// 獲得文件名            if (name != null) {              String nFname = newFileName;              if (schunk != null) {                nFname = schunk + "_" + name;              }              File savedFile = new File(uploadPath, nFname);              item.write(savedFile);            }          } else {            // 判斷是否帶分割信息            if (item.getFieldName().equals("chunk")) {              schunk = Integer.parseInt(item.getString());              //System.out.println(schunk);            }            if (item.getFieldName().equals("chunks")) {              schunks = Integer.parseInt(item.getString());            }            if (item.getFieldName().equals("name")) {              newFileName = new String(item.getString());            }          }        }        //System.out.println(schunk + "/" + schunks);        if (schunk != null && schunk == 1) {          TfileUploadStatus file = statusService.get(newFileName);          if (file != null) {            statusService.updateChunk(newFileName, schunk);          } else {            statusService.add(newFileName, schunk, schunks);          }        } else {          TfileUploadStatus file = statusService.get(newFileName);          if (file != null) {            statusService.updateChunk(newFileName, schunk);          }        }        if (schunk != null && schunk.intValue() == schunks.intValue()) {          outputStream = new BufferedOutputStream(new FileOutputStream(new File(uploadPath, newFileName)));          // 遍歷文件合并          for (int i = 1; i <= schunks; i++) {            //System.out.println("文件合并:" + i + "/" + schunks);            File tempFile = new File(uploadPath, i + "_" + name);            byte[] bytes = FileUtils.readFileToByteArray(tempFile);            outputStream.write(bytes);            outputStream.flush();            tempFile.delete();          }          outputStream.flush();        }        response.getWriter().write("{/"status/":true,/"newName/":/"" + newFileName + "/"}");      } catch (FileUploadException e) {        e.printStackTrace();        response.getWriter().write("{/"status/":false}");      } catch (Exception e) {        e.printStackTrace();        response.getWriter().write("{/"status/":false}");      } finally {        try {          if (outputStream != null)            outputStream.close();        } catch (IOException e) {          e.printStackTrace();        }      }    }  }}

android端源碼

UploadTask 上傳線程類

package com.mainaer.wjoklib.okhttp.upload;import android.database.sqlite.SQLiteDatabase;import android.os.Environment;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.text.TextUtils;import java.io.Closeable;import java.io.File;import java.io.IOException;import java.text.DecimalFormat;import java.util.HashMap;import java.util.Map;import okhttp3.Headers;import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;/** * 上傳線程 * * @author hst * @date 2016/9/6 . */  public class UploadTask implements Runnable {  private static String FILE_MODE = "rwd";  private OkHttpClient mClient;  private SQLiteDatabase db;  private UploadTaskListener mListener;  private Builder mBuilder;  private String id;// task id  private String url;// file url  private String fileName; // File name when saving  private int uploadStatus;  private int chunck, chuncks;//流塊  private int position;  private int errorCode;  static String BOUNDARY = "----------" + System.currentTimeMillis();  public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("multipart/form-data;boundary=" + BOUNDARY);  private UploadTask(Builder builder) {    mBuilder = builder;    mClient = new OkHttpClient();    this.id = mBuilder.id;    this.url = mBuilder.url;    this.fileName = mBuilder.fileName;    this.uploadStatus = mBuilder.uploadStatus;    this.chunck = mBuilder.chunck;    this.setmListener(mBuilder.listener);    // 以kb為計算單位  }  @Override  public void run() {    try {      int blockLength = 1024 * 1024;      File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator +fileName);      if (file.length() % blockLength == 0) {        chuncks = (int) file.length() / blockLength;      } else {        chuncks = (int) file.length() / blockLength + 1;      }      while (chunck <= chuncks&&uploadStatus!= UploadStatus.UPLOAD_STATUS_PAUSE&&uploadStatus!= UploadStatus.UPLOAD_STATUS_ERROR)      {        uploadStatus = UploadStatus.UPLOAD_STATUS_UPLOADING;        Map<String, String> params = new HashMap<String, String>();        params.put("name", fileName);        params.put("chunks", chuncks + "");        params.put("chunk", chunck + "");        final byte[] mBlock = FileUtils.getBlock((chunck - 1) * blockLength, file, blockLength);        MultipartBody.Builder builder = new MultipartBody.Builder()            .setType(MultipartBody.FORM);        addParams(builder, params);        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_MARKDOWN, mBlock);        builder.addFormDataPart("mFile", fileName, requestBody);        Request request = new Request.Builder()            .url(url+ "uploaderWithContinuinglyTransferring")            .post(builder.build())            .build();        Response response = null;        response = mClient.newCall(request).execute();        if (response.isSuccessful()) {          onCallBack();          chunck++;          /* if (chunck <= chuncks) {             run();          }*/        }        else        {          uploadStatus = UploadStatus.UPLOAD_STATUS_ERROR;          onCallBack();        }      }    } catch (IOException e) {      uploadStatus = UploadStatus.UPLOAD_STATUS_ERROR;      onCallBack();      e.printStackTrace();    }  }/*  *//**   * 刪除數據庫文件和已經上傳的文件   *//*  public void cancel() {    if (mListener != null)      mListener.onCancel(UploadTask.this);  }*/  /**   * 分發回調事件到ui層   */  private void onCallBack() {    mHandler.sendEmptyMessage(uploadStatus);    // 同步manager中的task信息    //UploadManager.getInstance().updateUploadTask(this);  }  Handler mHandler = new Handler(Looper.getMainLooper()) {    @Override    public void handleMessage(Message msg) {      int code = msg.what;      switch (code) {        // 上傳失敗        case UploadStatus.UPLOAD_STATUS_ERROR:          mListener.onError(UploadTask.this, errorCode,position);          break;        // 正在上傳        case UploadStatus.UPLOAD_STATUS_UPLOADING:          mListener.onUploading(UploadTask.this, getDownLoadPercent(), position);         // 暫停上傳          break;        case UploadStatus.UPLOAD_STATUS_PAUSE:          mListener.onPause(UploadTask.this);          break;      }    }  };  private String getDownLoadPercent() {    String baifenbi = "0";// 接受百分比的值    if (chunck >= chuncks) {      return "100";    }    double baiy = chunck * 1.0;    double baiz = chuncks * 1.0;    // 防止分母為0出現NoN    if (baiz > 0) {      double fen = (baiy / baiz) * 100;      //NumberFormat nf = NumberFormat.getPercentInstance();      //nf.setMinimumFractionDigits(2); //保留到小數點后幾位      // 百分比格式,后面不足2位的用0補齊      //baifenbi = nf.format(fen);      //注釋掉的也是一種方法      DecimalFormat df1 = new DecimalFormat("0");//0.00      baifenbi = df1.format(fen);    }    return baifenbi;  }  private String getFileNameFromUrl(String url) {    if (!TextUtils.isEmpty(url)) {      return url.substring(url.lastIndexOf("/") + 1);    }    return System.currentTimeMillis() + "";  }  private void close(Closeable closeable) {    try {      closeable.close();    } catch (IOException e) {      e.printStackTrace();    }  }  public void setClient(OkHttpClient mClient) {    this.mClient = mClient;  }  public Builder getBuilder() {    return mBuilder;  }  public void setBuilder(Builder builder) {    this.mBuilder = builder;  }  public String getId() {    if (!TextUtils.isEmpty(id)) {    } else {      id = url;    }    return id;  }  public String getUrl() {    return url;  }  public String getFileName() {    return fileName;  }  public void setUploadStatus(int uploadStatus) {    this.uploadStatus = uploadStatus;  }  public int getUploadStatus() {    return uploadStatus;  }  public void setmListener(UploadTaskListener mListener) {    this.mListener = mListener;  }  public static class Builder {    private String id;// task id    private String url;// file url    private String fileName; // File name when saving    private int uploadStatus = UploadStatus.UPLOAD_STATUS_INIT;    private int chunck;//第幾塊    private UploadTaskListener listener;    /**     * 作為上傳task開始、刪除、停止的key值,如果為空則默認是url     *     * @param id     * @return     */    public Builder setId(String id) {      this.id = id;      return this;    }    /**     * 上傳url(not null)     *     * @param url     * @return     */    public Builder setUrl(String url) {      this.url = url;      return this;    }    /**     * 設置上傳狀態     *     * @param uploadStatus     * @return     */    public Builder setUploadStatus(int uploadStatus) {      this.uploadStatus = uploadStatus;      return this;    }    /**     * 第幾塊     *     * @param chunck     * @return     */    public Builder setChunck(int chunck) {      this.chunck = chunck;      return this;    }    /**     * 設置文件名     *     * @param fileName     * @return     */    public Builder setFileName(String fileName) {      this.fileName = fileName;      return this;    }    /**     * 設置上傳回調     *     * @param listener     * @return     */    public Builder setListener(UploadTaskListener listener) {      this.listener = listener;      return this;    }    public UploadTask build() {      return new UploadTask(this);    }  }  private void addParams(MultipartBody.Builder builder, Map<String, String> params) {    if (params != null && !params.isEmpty()) {      for (String key : params.keySet()) {        builder.addPart(Headers.of("Content-Disposition", "form-data; name=/"" + key + "/""),            RequestBody.create(null, params.get(key)));      }    }  }}

UploadManager上傳管理器

package com.mainaer.wjoklib.okhttp.upload;import android.content.Context;import android.database.sqlite.SQLiteDatabase; import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; /** * 上傳管理器 * * @author wangjian * @date 2016/5/13 . */public class UploadManager {   private static Context mContext;   private static SQLiteDatabase db;  private OkHttpClient mClient;   private int mPoolSize = 20;  // 將執行結果保存在future變量中  private Map<string, future=""> mFutureMap;  private ExecutorService mExecutor;  private Map<string, uploadtask=""> mCurrentTaskList;   static UploadManager manager;   /**   * 方法加鎖,防止多線程操作時出現多個實例   */  private static synchronized void init() {    if (manager == null) {      manager = new UploadManager();    }  }   /**   * 獲得當前對象實例   *   * @return 當前實例對象   */  public final static UploadManager getInstance() {    if (manager == null) {      init();    }    return manager;  }   /**   * 管理器初始化,建議在application中調用   *   * @param context   */  public static void init(Context context, SQLiteDatabase db1) {    mContext = context;    db = db1;    getInstance();  }   public UploadManager() {    initOkhttpClient();     // 初始化線程池    mExecutor = Executors.newFixedThreadPool(mPoolSize);    mFutureMap = new HashMap<>();    mCurrentTaskList = new HashMap<>();  }   /**   * 初始化okhttp   */  private void initOkhttpClient() {    OkHttpClient.Builder okBuilder = new OkHttpClient.Builder();    okBuilder.connectTimeout(1000, TimeUnit.SECONDS);    okBuilder.readTimeout(1000, TimeUnit.SECONDS);    okBuilder.writeTimeout(1000, TimeUnit.SECONDS);    mClient = okBuilder.build();  }   /**   * 添加上傳任務   *   * @param uploadTask   */  public void addUploadTask(UploadTask uploadTask) {    if (uploadTask != null && !isUploading(uploadTask)) {      uploadTask.setClient(mClient);      uploadTask.setUploadStatus(UploadStatus.UPLOAD_STATUS_INIT);      // 保存上傳task列表      mCurrentTaskList.put(uploadTask.getId(), uploadTask);      Future future = mExecutor.submit(uploadTask);      mFutureMap.put(uploadTask.getId(), future);    }  }   private boolean isUploading(UploadTask task) {    if (task != null) {      if (task.getUploadStatus() == UploadStatus.UPLOAD_STATUS_UPLOADING) {        return true;      }    }    return false;  }   /**   * 暫停上傳任務   *   * @param id 任務id   */  public void pause(String id) {    UploadTask task = getUploadTask(id);    if (task != null) {      task.setUploadStatus(UploadStatus.UPLOAD_STATUS_PAUSE);    }  }   /**   * 重新開始已經暫停的上傳任務   *   * @param id 任務id   */  public void resume(String id, UploadTaskListener listener) {    UploadTask task = getUploadTask(id);    if (task != null) {      addUploadTask(task);    }  } /*  *//**   * 取消上傳任務(同時會刪除已經上傳的文件,和清空數據庫緩存)   *   * @param id    任務id   * @param listener   *//*  public void cancel(String id, UploadTaskListener listener) {    UploadTask task = getUploadTask(id);    if (task != null) {      mCurrentTaskList.remove(id);      mFutureMap.remove(id);      task.setmListener(listener);      task.cancel();      task.setDownloadStatus(UploadStatus.DOWNLOAD_STATUS_CANCEL);    }  }*/   /**   * 實時更新manager中的task信息   *   * @param task   */  public void updateUploadTask(UploadTask task) {    if (task != null) {      UploadTask currTask = getUploadTask(task.getId());      if (currTask != null) {        mCurrentTaskList.put(task.getId(), task);      }    }  }   /**   * 獲得指定的task   *   * @param id task id   * @return   */  public UploadTask getUploadTask(String id) {    UploadTask currTask = mCurrentTaskList.get(id);    if (currTask == null) {        currTask = parseEntity2Task(new UploadTask.Builder().build());        // 放入task list中        mCurrentTaskList.put(id, currTask);    }     return currTask;  }    private UploadTask parseEntity2Task(UploadTask currTask) {     UploadTask.Builder builder = new UploadTask.Builder()//        .setUploadStatus(currTask.getUploadStatus())        .setFileName(currTask.getFileName())//        .setUrl(currTask.getUrl())        .setId(currTask.getId());       currTask.setBuilder(builder);     return currTask;  }} 

FileUtils文件分塊類

package com.mainaer.wjoklib.okhttp.upload;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;public class FileUtils {  public static byte[] getBlock(long offset, File file, int blockSize) {    byte[] result = new byte[blockSize];    RandomAccessFile accessFile = null;    try {      accessFile = new RandomAccessFile(file, "r");      accessFile.seek(offset);      int readSize = accessFile.read(result);      if (readSize == -1) {        return null;      } else if (readSize == blockSize) {        return result;      } else {        byte[] tmpByte = new byte[readSize];        System.arraycopy(result, 0, tmpByte, 0, readSize);        return tmpByte;      }    } catch (IOException e) {      e.printStackTrace();    } finally {      if (accessFile != null) {        try {          accessFile.close();        } catch (IOException e1) {        }      }    }    return null;  }}

UploadTaskListener 接口類

package com.mainaer.wjoklib.okhttp.upload; import com.mainaer.wjoklib.okhttp.download.DownloadStatus;import java.io.File;/** * Created by hst on 16/9/21. */public interface UploadTaskListener {  /**   * 上傳中   *   * @param percent   * @param uploadTask   */  void onUploading(UploadTask uploadTask, String percent,int position)   /**   * 上傳成功   *   * @param file   * @param uploadTask   */  void onUploadSuccess(UploadTask uploadTask, File file);   /**   * 上傳失敗   *   * @param uploadTask   * @param errorCode  {@link DownloadStatus}   */  void onError(UploadTask uploadTask, int errorCode,int position);     /**  * 上傳暫停  *  * @param uploadTask  *  */  void onPause(UploadTask uploadTask); } 

源碼下載:okhttpUpLoader_jb51.rar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 称多县| 弥渡县| 安福县| 南安市| 固镇县| 五原县| 类乌齐县| 从江县| 邵武市| 牟定县| 桦甸市| 泉州市| 镇江市| 奈曼旗| 敦化市| 普宁市| 天峨县| 巴东县| 孟州市| 法库县| 景宁| 巴南区| 宜黄县| 乐亭县| 馆陶县| 凭祥市| 华安县| 崇州市| 报价| 台山市| 榆林市| 大埔区| 安泽县| 自贡市| 新巴尔虎左旗| 四平市| 色达县| 古田县| 油尖旺区| 衡阳县| 铁岭市|