Android实现单一文件下载

好记性不如烂笔头啊,今天分享下我最近弄得一个文件下载的东东,虽然只是单一下载但是对初学者可能有借鉴意义吧,高手就忽略吧,也希望大家有想法提出来一起进步哈。(第一次写博文)


原理:由client端发起request请求,由server端读取本地文件,由response对象返回文件流。


服务器端代码:

@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		ServletOutputStream op = null;
		try {
			response.setContentType("text/html;charset=GBK");
			byte[] data = 读取文件获取字节数组;
			if(data==null){
				process("数据为空".getBytes(),op);
				return;
			}
			response.addHeader("content-length", data.length+"");
			response.setHeader("content-disposition", "attachment; filename="
			+ new String(fileName.getBytes("GBK"), "ISO8859_1"));
			if (request.getSession().getServletContext().getMimeType(fileName) == null)
				response.setContentType("Application/octet-stream;charset=GBK");
			else
				response.setContentType(request.getSession()
						.getServletContext().getMimeType(fileName));
			op = response.getOutputStream();
			op.write(data, 0, data.length);
			op.flush();
			op.close();
		} catch (Exception e) {
			e.printStackTrace();
			process((e.getMessage() == null ? "空指针" : e.getMessage()).getBytes(), op);
		}

	}

	private void process(byte[] data, ServletOutputStream op) {
		try {
		
			op.write(data, 0, data.length);
			op.flush();
			op.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

读取文件的代码以及下载文件所必要的逻辑检查等我就忽略了,根据需求不同各自实现。

注意:

op=response.getOutputStream()此行代码一定要在response的header细心都设定之后再获取,因为代码顺序的原因会找出一些header信息的乱码比如文件名,所以大家要注意,好多人都遇到这个问题,包括ME。

下面是client端代码,我在客户端下载的时候,是再开一个线程。

@Override
	protected void onActivityResult(int requestCode, int resultCode, final Intent data) {

		switch (resultCode) {
		case RESULT_OK:
			final Handler m_Handler = new Handler(){

				@Override
				public void handleMessage(Message msg) {
					if(msg.what == 0){
						ComponentActivity.this.fileDownLoaderDialog.setMax(msg.getData().getInt("maxsize"));
					}else if(msg.what == 1){
						ComponentActivity.this.fileDownLoaderDialog.setProgress(msg.getData().getInt("downloader"));
					}else if(msg.what == 2){
						ComponentActivity.this.fileDownLoaderDialog.dismiss();
						final String filePath =  msg.getData().getString("filepath");
						new AlertDialog.Builder(ComponentActivity.this)
						.setTitle("下载提示:")
						.setMessage(msg.getData().getString("message"))
						.setPositiveButton("打开", new DialogInterface.OnClickListener(){ 
							@Override 
							public void onClick(DialogInterface dialog, int which){
								Intent intent = AndroidFileUtil.openFile(filePath);
								try {
									ComponentActivity.this.startActivity(intent);
								} catch (Exception e) {
									intent = AndroidFileUtil.getAllIntent(filePath);
									ComponentActivity.this.startActivity(intent);
								}
							} 
						})
						.setNegativeButton("取消", new DialogInterface.OnClickListener(){ 
							@Override 
							public void onClick(DialogInterface dialog, int which){
								dialog.dismiss(); 
							} 
						})
						.show();
					}else if(msg.what == 3){
						new AlertDialog.Builder(ComponentActivity.this)
						.setTitle("下载提示:")
						.setMessage("文件已经存在是否要覆盖?")
						.setPositiveButton("确定", new DialogInterface.OnClickListener(){ 
							@Override 
							public void onClick(DialogInterface dialog, int which){
								downLoad.start();
								dialog.dismiss(); 
							}
						})
						.setNegativeButton("取消下载", new DialogInterface.OnClickListener(){ 
							@Override 
							public void onClick(DialogInterface dialog, int which){
								if(thread != null && !thread.isInterrupted()){
									httpconn.disconnect();
									thread.interrupt();
								}
								dialog.dismiss(); 
							} 
						})
						.show();
					}else if(msg.what == 4){
						ComponentActivity.this.showDialog(1);
					}else if(msg.what == -1){
						ComponentActivity.this.fileDownLoaderDialog.dismiss();
						new AlertDialog.Builder(ComponentActivity.this)
						.setTitle("下载提示:")
						.setMessage(msg.getData().getString("message"))
						.setNegativeButton("确定", new DialogInterface.OnClickListener(){ 
							@Override 
							public void onClick(DialogInterface dialog, int which){
								dialog.dismiss(); 
							} 
						})
						.show();
					}
					super.handleMessage(msg); 
				}

			};
			downLoad = new Thread(new Runnable(){
				@Override
				public void run() {
					try {
						Thread.sleep(100);
					    Message message; 
					    Bundle bund;
					    //*****************提示下载框*********************
					    message = new Message();
					    bund = new Bundle();
					    message.what = 4;
					    message.setData(bund);
					    m_Handler.sendMessageDelayed(message,0);
					    //**************************************
						Bundle bundle = data.getExtras();
						String savepath = bundle.getString("savePath");
						InputStream dis = httpconn.getInputStream();
						String fileName = httpconn.getHeaderField("content-disposition");
						fileName = new String(fileName.getBytes("iso8859-1"),"gbk");
						File newFile = new File(savepath + File.separator + fileName.split("=")[1]);
						//*****************设置进度最大值*********************
						message = new Message();
						bund = new Bundle();
						bund.putInt("maxsize", httpconn.getContentLength());
						message.what = 0;
						message.setData(bund);
						m_Handler.sendMessageDelayed(message,0);
						//**************************************
						FileOutputStream fos = new FileOutputStream(newFile);
						byte[] buffer = new byte[1024];
						int len;
						int downloader = 0;
						try {
							while ((len = dis.read(buffer)) != -1) {
								fos.write(buffer, 0, len);
								downloader += len;
								//*****************更新UI主线程显示当前累计下载量*********************
								message = new Message();
								bund = new Bundle();
								bund.putInt("downloader", downloader);
								message.what = 1;
								message.setData(bund);
								m_Handler.sendMessageDelayed(message,0);
								//**************************************
							}
							fos.flush();
							fos.close();
							//*****************更新UI主线程提示文件下载完成*********************
							message = new Message();
							bund = new Bundle();
							message.what = 2;
							bund.putString("filepath", newFile.getAbsolutePath());
							bund.putString("message", "文件下载成功!");
							message.setData(bund);
							m_Handler.sendMessageDelayed(message,0);
							//**************************************
						} catch (Exception e) {
							Log.e("downloader error", e.getMessage());
						}finally{
							dis.close();
							httpconn.disconnect();
						}
					} catch (InterruptedException e) {
						Thread.currentThread().interrupt();
					} catch (MalformedURLException e) {
						Log.e("error", e.getMessage());
						//**************************************
						Message message = new Message();
						Bundle bund = new Bundle();
						message.what = -1;
						bund.putString("message", "文件下载路径不正确,下载失败!");
						message.setData(bund);
						m_Handler.sendMessageDelayed(message,0);
						//**************************************
					} catch (IOException e) {
						Log.e("error", e.getMessage());
						//**************************************
						Message message = new Message();
						Bundle bund = new Bundle();
						message.what = -1;
						bund.putString("message", "读取文件流异常,下载失败!");
						message.setData(bund);
						m_Handler.sendMessageDelayed(message,0);
						//**************************************
					}
				}
				
			});
			thread = new Thread(new Runnable(){
				@Override
				public void run() {
					try {
						Thread.sleep(100);
					    Message message; 
					    Bundle bund;
						Bundle bundle = data.getExtras();
						String savepath = bundle.getString("savePath");
						String url = bundle.getString("url");
						httpconn = (HttpURLConnection) new URL(url).openConnection();
						httpconn.setRequestMethod("GET");
						httpconn.setDoInput(true);
						httpconn.setDoOutput(true);
						httpconn.setUseCaches(false);
						httpconn.setInstanceFollowRedirects(true);
						httpconn.connect();
						String fileName = httpconn.getHeaderField("content-disposition");
						fileName = new String(fileName.getBytes("iso8859-1"),"gbk");
						Log.w("File Name is...", fileName);
						File newFile = new File(savepath + File.separator + fileName.split("=")[1]);
						if(newFile.exists()){
							//*****************更新主线程UI提示文件覆盖选择*********************
							message = new Message();
							bund = new Bundle();
							message.what = 3;
							message.setData(bund);
							m_Handler.sendMessageDelayed(message,0);
						}else{
							newFile.createNewFile();
							downLoad.start();
						}
					} catch (InterruptedException e) {
						Thread.currentThread().interrupt();
					} catch (MalformedURLException e) {
						Log.e("error", e.getMessage());
						//**************************************
						Message message = new Message();
						Bundle bund = new Bundle();
						message.what = -1;
						bund.putString("message", "文件下载路径不正确,下载失败!");
						message.setData(bund);
						m_Handler.sendMessageDelayed(message,0);
						//**************************************
					} catch (IOException e) {
						Log.e("error", e.getMessage());
						//**************************************
						Message message = new Message();
						Bundle bund = new Bundle();
						message.what = -1;
						bund.putString("message", "读取文件流异常,下载失败!");
						message.setData(bund);
						m_Handler.sendMessageDelayed(message,0);
						//**************************************
					}
				}
			});
			thread.start();
			break;
		default:
			break;
		}
	}

因为在下载的时候要让用户来选择文件的保存目录,所以在用户要进行下载时首先是提示用户选择保存目录的,要打开FileBrowserActivity.java(后续文章呈现),所以就在

onActivityResult方法中实现了文件下载,这个因具体功能要求而异。

解释:在此处为何要用2个Thread来进行文件下载,实际上是我技术太差吧,呵呵。因为在httpconnect连接了之后我要获取fileName,检查文件在用户所选的目录是不是已经存在,第一个线程只是连接httpconnect获取文件名进行检查,如若用户选择覆盖下载,则执行读取inputstream,然后写入文件中。在此处用了
iso8859-1编码是因为我们的服务端也是同样的编码(也是为了兼容IOS),这个必须要统一。

具体代码就这么多,有好的想法提出来,一起进步我也是菜鸟一枚。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值