[Android]Android FTP server based on Apache FTPServer

老板让做的用Android做热点,同时作为FTP服务器。网上的都在吐槽其他人的不好使,结果页没有一个能好使的,最后还是靠Stack Overflow完成了初试验!

在我的电脑或者浏览器里输入FTP地址、账号密码就能实现文件互传了!HIAHIAHIA!


Apache官网可以下载最新的Apache FtpServer 1.0.6 Release,先将解压后\apache-ftpserver-1.0.6\common\lib路径下的

这几个jar包复制到project/libs内,然后Eclipse内打开project,在project上右键-->properties-->Java Build Path-->Libraries-->Add External JARs,选择刚才导入的几个jar包。

由于要使用一个用户配置文件的copy,所以在project/res/下新建raw文件夹,新建文件users.properties,复制如下内容:

# Licensed to the Apache Software Foundation (ASF) under one  
# or more contributor license agreements.  See the NOTICE file  
# distributed with this work for additional information  
# reanonymousding copyright ownership.  The ASF licenses this file  
# to you 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.  
  
# Password is "admin"  
ftpserver.user.admin.userpassword=admin  
  
ftpserver.user.admin.homedirectory=/
ftpserver.user.admin.enableflag=true  
ftpserver.user.admin.writepermission=true  
ftpserver.user.admin.maxloginnumber=20  
ftpserver.user.admin.maxloginperip=5 
ftpserver.user.admin.idletime=300  
ftpserver.user.admin.uploadrate=4800000  
ftpserver.user.admin.downloadrate=4800000  
  
ftpserver.user.anonymous.userpassword=
ftpserver.user.anonymous.homedirectory=/
ftpserver.user.anonymous.enableflag=true  
ftpserver.user.anonymous.writepermission=true  
ftpserver.user.anonymous.maxloginnumber=20  
ftpserver.user.anonymous.maxloginperip=5  
ftpserver.user.anonymous.idletime=300  
ftpserver.user.anonymous.uploadrate=4800000  
ftpserver.user.anonymous.downloadrate=4800000
然后在AndroidManifest.xml文件内添加权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >  </uses-permission>  
<uses-permission android:name="android.permission.INTERNET" >  </uses-permission>  
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >  </uses-permission>  
<uses-permission android:name="android.permission.READ_PHONE_STATE" >  </uses-permission>  
<uses-permission android:name="android.permission.WAKE_LOCK" >  </uses-permission>  
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >  </uses-permission>
下面上代码:

FTPLetImpl.java

package com.example.ftptest02;

import java.io.IOException;

import org.apache.ftpserver.ftplet.DefaultFtplet;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.ftplet.FtpSession;
import org.apache.ftpserver.ftplet.FtpletResult;

public class FTPLetImpl extends DefaultFtplet {

    @Override
    public FtpletResult onLogin(FtpSession session, FtpRequest request) throws FtpException, IOException {
        System.out.println(session.getUser().getName() + " Logged in");
        return super.onLogin(session, request);
    }

    @Override
    public FtpletResult onDisconnect(FtpSession session) throws FtpException, IOException {
        System.out.println(session.getUser().getName() + " Disconnected");
        return super.onDisconnect(session);
    }

    @Override
    public FtpletResult onDownloadStart(FtpSession session, FtpRequest request) throws FtpException, IOException {
        System.out.println(session.getUser().getName() + " Started Downloading File " + request.getArgument());
        return super.onDownloadStart(session, request);
    }

    @Override
    public FtpletResult onDownloadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
        System.out.println("Finished Downloading " + request.getArgument());
        return super.onDownloadEnd(session, request);
    }

}
SFTPServer.java

package com.example.ftptest02;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.ftpserver.ConnectionConfigFactory;
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.ConcurrentLoginPermission;
import org.apache.ftpserver.usermanager.impl.TransferRatePermission;
import org.apache.ftpserver.usermanager.impl.WritePermission;

import android.os.Environment;

public class SFTPServer {
	// ===========================================================
    // Constants
    // ===========================================================
    private final int FTP_PORT = 2221;
    private final String DEFAULT_LISTENER = "default";
    // private final Logger LOG = LoggerFactory.getLogger(SFTPServer.class);
    private static final List<Authority> ADMIN_AUTHORITIES;
    private static final int BYTES_PER_KB = 1024;
    private static String ftpConfigDir= Environment.getExternalStorageDirectory().getAbsolutePath()+"/ftpConfig/";
    private static final String DEFAULT_USER_DIR = ftpConfigDir;

    public final static int MAX_CONCURRENT_LOGINS = 1;
    public final static int MAX_CONCURRENT_LOGINS_PER_IP = 1; 

    // ===========================================================
    // Fields
    // ===========================================================
    private static FtpServer mFTPServer;
    private static UserManager mUserManager;
    private static FtpServerFactory mFTPServerFactory;
    private ListenerFactory mListenerFactor;

    // ===========================================================
    // Constructors
    // ===========================================================
    static {
        // Admin Authorities
        ADMIN_AUTHORITIES = new ArrayList<Authority>();
        ADMIN_AUTHORITIES.add(new WritePermission());
        ADMIN_AUTHORITIES.add(new ConcurrentLoginPermission(MAX_CONCURRENT_LOGINS, MAX_CONCURRENT_LOGINS_PER_IP));
        ADMIN_AUTHORITIES.add(new TransferRatePermission(Integer.MAX_VALUE, Integer.MAX_VALUE));
    }

    // ===========================================================
    // Getter & Setter
    // ===========================================================

    // ===========================================================
    // Methods for/from SuperClass/Interfaces
    // ===========================================================

    // ===========================================================
    // Methods
    // ===========================================================
    public void init() throws FtpException {
        mFTPServerFactory = new FtpServerFactory();
        mListenerFactor = new ListenerFactory();
        mListenerFactor.setPort(FTP_PORT);
        
        //anonymous login
        //seems no need
        //ConnectionConfigFactory connectionConfigFactory = new ConnectionConfigFactory();
        //connectionConfigFactory.setAnonymousLoginEnabled(true);
        //mFTPServerFactory.setConnectionConfig(connectionConfigFactory.createConnectionConfig());

        mFTPServerFactory.addListener(DEFAULT_LISTENER, mListenerFactor.createListener());
        mFTPServerFactory.getFtplets().put(FTPLetImpl.class.getName(), new FTPLetImpl());

        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        
        userManagerFactory.setFile(new File(ftpConfigDir + "users.properties"));
        userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
        mUserManager = userManagerFactory.createUserManager();
        mFTPServerFactory.setUserManager(mUserManager);

        this.createAdminUser();
        SFTPServer.addUser("admin1", "123456", 20, 20);
        //SFTPServer.addUser("gar", "gar", 100, 100);
        //this works
        //SFTPServer.addUser("anonymous", "", 20, 20);
        
        mFTPServer = mFTPServerFactory.createServer();

        mFTPServer.start();
    }

    private UserManager createAdminUser() throws FtpException {
        UserManager userManager = mFTPServerFactory.getUserManager();
        String adminName = userManager.getAdminName();
        
        System.out.println(adminName);

        if (!userManager.doesExist(adminName)) {
            // LOG.info((new
            // StringBuilder()).append("Creating user : ").append(adminName).toString());
            BaseUser adminUser = new BaseUser();
            adminUser.setName(adminName);
            adminUser.setPassword(adminName);
            adminUser.setEnabled(true);
            adminUser.setAuthorities(ADMIN_AUTHORITIES);
            adminUser.setHomeDirectory(DEFAULT_USER_DIR);
            adminUser.setMaxIdleTime(0);
            userManager.save(adminUser);
        }

        return userManager;
    }

    public static void addUser(String username, String password, int uploadRateKB, int downloadRateKB) throws FtpException {

        BaseUser user = new BaseUser();
        user.setName(username);
        user.setPassword(password);
        user.setHomeDirectory(DEFAULT_USER_DIR);
        user.setEnabled(true);
        
        //BaseUser anonuser = new BaseUser();
        //anonuser = new BaseUser(user);
        //anonuser.setName("anonymous");

        List<Authority> list = new ArrayList<Authority>();
        list.add(new TransferRatePermission(downloadRateKB * BYTES_PER_KB, uploadRateKB * BYTES_PER_KB)); // 20KB
        list.add(new ConcurrentLoginPermission(MAX_CONCURRENT_LOGINS, MAX_CONCURRENT_LOGINS_PER_IP));
        //write permission
        //list.add(new WritePermission());

        user.setAuthorities(list);

        mFTPServerFactory.getUserManager().save(user);
    }
    

    public static void restartFTP() throws FtpException {
        if (mFTPServer != null) {
            mFTPServer.stop();
            try {
                Thread.sleep(1000 * 3);
            } catch (InterruptedException e) {
            }
            mFTPServer.start();
        }
    }

    public static void stopFTP() throws FtpException {
        if (mFTPServer != null) {
            mFTPServer.stop();
            System.out.println("server stoped");
        }
    }

    public static void pauseFTP() throws FtpException {
        if (mFTPServer != null) {
            mFTPServer.suspend();
        }
    }

    public static void resumeFTP() throws FtpException {
        if (mFTPServer != null) {
            mFTPServer.resume();
        }
    }

    // ===========================================================
    // Inner and Anonymous Classes
    // ===========================================================

}

开始的时候不好使是因为没有写user类,实际上就没有添加user,即使拷贝了用户配置文件,所以仍旧无法访问;

现在也只是能添加用户,匿名登陆似乎不是十分完善,密码设为空时直接就能登录了。。。


MainActivity.java

package com.example.ftptest02;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

import org.apache.ftpserver.ftplet.FtpException;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends Activity {
	
	public static String hostip;
	private static String ftpConfigDir= Environment.getExternalStorageDirectory().getAbsolutePath()+"/ftpConfig/";
	String state;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        TextView tv=(TextView)findViewById(R.id.tvText);  
        String info="请通过浏览器或者我的电脑访问以下地址\n"+"ftp://"+getLocalIpAddress()+":2221\n";  
        hostip = getLocalIpAddress();
        state = Environment.getExternalStorageState();
        System.out.println(state.equals(Environment.MEDIA_MOUNTED));
        System.out.println(Environment.getExternalStorageDirectory().getAbsolutePath());
        System.out.println("hosip->>" + hostip);
        tv.setText(info);  
        
        Runnable myRunnable = new MyRunnable();
        Thread myThread = new Thread(myRunnable);
        myThread.start();
        
    }
    
    class MyRunnable implements Runnable {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			File f=new File(ftpConfigDir);  
	        if(!f.exists())  
	            f.mkdir();  
	        copyResourceFile(R.raw.users, ftpConfigDir + "users.properties");  
	        try {
	        	new SFTPServer().init();
			} catch (FtpException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}  
	        System.out.println("server is on");
		}
    }
    
    public String getLocalIpAddress() {  
        String strIP=null;  
        try {  
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {  
                NetworkInterface intf = en.nextElement();  
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {  
                    InetAddress inetAddress = enumIpAddr.nextElement();  
                    if (!inetAddress.isLoopbackAddress()) {  
                        strIP= inetAddress.getHostAddress().toString();  
                    }  
                }  
            }  
        } catch (SocketException ex) {  
            Log.e("msg", ex.toString());  
        }  
        return strIP;  
    }  
    
    private void copyResourceFile(int rid, String targetFile){  
        InputStream fin = ((Context)this).getResources().openRawResource(rid);  
        FileOutputStream fos=null;  
        int length;  
        try {  
            fos = new FileOutputStream(targetFile);  
            byte[] buffer = new byte[1024];   
            while( (length = fin.read(buffer)) != -1){  
                fos.write(buffer,0,length);  
            }  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally{  
            if(fin!=null){  
                try {  
                    fin.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
             if(fos!=null){  
                 try {  
                    fos.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
             }  
        }  
    }  
}
这个layout比较简单,就不贴了,自己写一下就OK,连个按钮都不用。

直接用Android设备作为热点并实现FTP服务器也已经实现,过两天整理一下记录一下。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值