FTP客户端实则是相对于远程文件的一个文件管理器,主要的功能有登录,下载,上传,剪切,粘贴,新建文件夹,重命名,删除文件,查看文件属性,同步等等。其实同步也就是上传,只是把上传功能修饰了一下罢了,应用需要引入一个ftp4j.jar的库。那就先说说整个客户端的代码逻辑吧。
用户进入应用后首先进入的是登录连接服务器,获取一个ftpclient引用,有了它你就能为所欲为了,呵。获取ftpClient之后我们就可以进行文件浏览和操作了,文件操作大都比较简单,就挑几个重点的吧。一个是剪切,剪切的时候只需要将选择的文件的绝对路径存储到SharedPreferences,等到调用粘贴的时候再调用剪切ftpClient.reName(oldName,newName)方法便可实现剪切功能。另一个就是同步,同步功能是将从服务端下载过而在本地又修改过的资源进行上传进而覆盖掉服务端的资源,达到更新的目的。笔者实现同步功能的做法是首先在下载的时候将下载的文件对应于服务端的绝对路径、下载时间、下载到本地的路径存储于数据库,每次用户进入应用的时候对数据库进行更新,将存在有记录而没有对应文件的记录删除。然后当用户点击同步的时候就逐一进行最后修改时间对比,找到有修改过的文件便对其进行上传到ftp的相应目录进行覆盖,再对数据库进行更新。
ftp基本操作代码
/** * 删除服务器上指定文件 * * @throws FTPException * @throws FTPIllegalReplyException * @throws IOException * @throws IllegalStateException * */ public static void removeFTPFile(FTPClient ftpClient, String removeFilePath, boolean isDirectory) throws IllegalStateException, IOException, FTPIllegalReplyException, FTPException { if (isDirectory) { ftpClient.deleteDirectory(removeFilePath); return; } ftpClient.deleteFile(removeFilePath); } /** * 给服务器上的文件进行重命名 * */ public static void renameFTPFile(Context context, final FTPClient ftpClient, final FTPFile file) { Builder builder = new AlertDialog.Builder(context); // 设置对话框的标题 builder.setTitle("重命名"); final EditText edit = new EditText(context); edit.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); edit.setHint(file.getName()); builder.setView(edit); builder.setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (edit.getText() != null && !"".equals(edit.getText())) { try { ftpClient.rename(file.getName(), edit.getText() .toString()); } catch (Exception e) { e.printStackTrace(); } } } }); builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); } /** * 剪切 * */ public static void cutFTPFile(SavePreferencesData savePreData, String cutFTPFileAbsolutePath) { savePreData.putStringData("cut", cutFTPFileAbsolutePath); } /** * 粘贴 * * @throws FTPException * @throws FTPIllegalReplyException * @throws IOException * @throws IllegalStateException * */ public static void pasteFTPFile(SavePreferencesData savePreData, FTPClient ftpClient, String newPath) throws IllegalStateException, IOException, FTPIllegalReplyException, FTPException { String cutPath = savePreData.getStringData("cut"); if (!"".equals(cutPath)) { ftpClient.rename( cutPath, newPath + "/" + cutPath.substring(cutPath.lastIndexOf("/") + 1, cutPath.length())); savePreData.clear(); } } /** * 显示文件属性 * */ public static void showFTPFileProperty(Context context, FTPFile file) { Builder builder = new AlertDialog.Builder(context); // 设置对话框的标题 builder.setTitle("属性"); String type = file.getType() == FTPFile.TYPE_DIRECTORY ? "文件夹" : "文件"; builder.setMessage("文件名: " + file.getName() + " \n 文件类型: " + type + "\n 文件大小: " + file.getSize() + " 字节 \n 上次修改时间: " + file.getModifiedDate()); builder.create().show(); } /** * 下载指定文件 * */ public static void downloadFTPFile(FTPUtil util, Map<String, String> item) { util.setFile(item); util.preTransFile(); } /** * 新建文件夹 * */ public static void newFTPFileDirectory(Context context, final FTPClient ftpClient) throws IllegalStateException, IOException, FTPIllegalReplyException, FTPException { Builder builder = new AlertDialog.Builder(context); // 设置对话框的标题 builder.setTitle("新建文件夹"); final EditText edit = new EditText(context); edit.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); builder.setView(edit); builder.setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (edit.getText() != null && !"".equals(edit.getText())) { try { ftpClient.createDirectory(edit.getText().toString()); } catch (Exception e) { e.printStackTrace(); } } } }); builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); }ftp上传下载功能实现
/** * 传输文件 * * @throws FTPAbortedException * @throws FTPDataTransferException * @throws FTPException * @throws FTPIllegalReplyException * @throws IOException * @throws FileNotFoundException * @throws IllegalStateException */ private void transFile() throws IllegalStateException, FileNotFoundException, IOException, FTPIllegalReplyException, FTPException, FTPDataTransferException, FTPAbortedException { operateType = (String) mQueue.get(0).keySet().toArray()[0]; filePath = mQueue.get(0).get(operateType); if (operateType.equals(Constants.TYPE_DOWNLOAD)) { File file = new File(Constants.workSpace + filePath.substring(filePath.lastIndexOf("/") + 1, filePath.length())); mFtpClient .download(filePath, file, new MyFTPDataTransferListener()); } else if (operateType.equals(Constants.TYPE_UPLOAD)) { File file = new File(filePath); if (file.exists()) { System.out.println("upload path ----> " + uploadPathQueue.get(0)); mFtpClient.changeDirectory(uploadPathQueue.get(0)); mFtpClient.upload(file, new MyFTPDataTransferListener()); } } }ftp登录和注销功能
/** * 这里在外面有非ui线程来处理 * * @param host * ftp主机 * @param port * 端口 * @param username * 用户名 * @param password * 密码 */ public FTPClient login(String host, int port, String username, String password) { if (null != mFtpClient) return mFtpClient; try { mFtpClient = new FTPClient(); mFtpClient.connect(host, port); mFtpClient.login(username, password, null); return mFtpClient; } catch (Exception e) { e.printStackTrace(); Toast.makeText(context, "连接服务器失败", Toast.LENGTH_LONG).show(); } return null; } /** * 注销 */ public void logout() { if (null != mFtpClient) { try { mFtpClient.logout(); mFtpClient.disconnect(true); } catch (IOException e) { e.printStackTrace(); } catch (FTPIllegalReplyException e) { e.printStackTrace(); } catch (FTPException e) { e.printStackTrace(); } } }