2013-08-22 137 views
0

我想将现有的文件从我的Android上传到FTP服务器。Android FTP文件上传

以下代码有效,但只在其自己的项目中有效。

public class FtpConnectDemo { 
    public static void main(String[] args) { 
     uploadDatei(SERVER, "SERVER/htdocs/wa/data/ArtikelDatenbank.csv", "ArtikelDatenbank.csv", USER, PASSWORD); 
    } 



    public static void uploadDatei(String ftpServer, String pfadUndDateiName, String dateiName, String benutzer, String passwort) { 
     StringBuffer sb = new StringBuffer("ftp://"); 

     sb.append(benutzer); 
     sb.append(':'); 
     sb.append(passwort); 
     sb.append('@'); 
     sb.append(ftpServer); 
     sb.append('/'); 
     sb.append(pfadUndDateiName); 
     sb.append(";type=a"); 

     BufferedInputStream bis = null; 
     BufferedOutputStream bos = null; 
     try { 
      URL url = new URL(sb.toString()); 
      URLConnection urlc = url.openConnection(); 

      bos = new BufferedOutputStream(urlc.getOutputStream()); 
      bis = new BufferedInputStream(new FileInputStream(dateiName)); 

      int i; 
      // read byte by byte until end of stream 
      while ((i = bis.read()) != -1) { 
       bos.write(i); 
      } 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (bis != null) { 
       try { 
        bis.close(); 
       } catch (IOException ioe) { 
        ioe.printStackTrace(); 
       } 
      } 
      if (bos != null) { 
       try { 
        bos.close(); 
       } catch (IOException ioe) { 
        ioe.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

如果我将此代码包含到我的其他项目中,则不再有效。该方法通过点击按钮来调用。 onClickListener应该调用第二种方法uploadCsvAufServer()

这是我的另一个项目。

调用方法:

private void initObjekte() { 

     dbHelper = new DBController(this); 

     this.buttonSync = (Button) this.findViewById(R.id.button_sync); 
     this.buttonSync.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 
       // 1. Erstellen einer csv-Datei, die die Werte aus 1. enthält: OK 
       Synchronisierung.this.saveUpdateDateiAufSdCard(); 

       // 2. Kopieren der Datei auf den Webserver 
       Synchronisierung.this.uploadCsvAufServer(); 

       // Bisher als "nein" gekennzeichnete Werte werden als sychronisiert markiert und auf "ja" gesetzt 
       Synchronisierung.this.dbHelper.updateSyncStatus(); 
       Synchronisierung.this.getNichtSyncedDaten(); 
      } 
     }); 
} 

调用的方法:

public void uploadCsvAufServer() { 

    StringBuffer sb = new StringBuffer("ftp://"); 
    sb.append(this.BENUTZER); 
    sb.append(':'); 
    sb.append(this.PASSWORT); 
    sb.append('@'); 
    sb.append(this.SERVER); 
    sb.append('/'); 
    sb.append(this.SERVER_DATEINAME); 
    sb.append(";type=a"); 

    BufferedInputStream bis = null; 
    BufferedOutputStream bos = null; 
    try { 
     URL url = new URL(sb.toString()); 
     URLConnection urlc = url.openConnection(); 

     bos = new BufferedOutputStream(urlc.getOutputStream()); 
     bis = new BufferedInputStream(new FileInputStream(this.DATEINAME)); 

     int i; 
     // read byte by byte until end of stream 
     while ((i = bis.read()) != -1) 
     { 
      bos.write(i); 
     } 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (bis != null) { 
      try 
      { 
       bis.close(); 
      } catch (IOException ioe) 
      { 
       ioe.printStackTrace(); 
      } 
     } 
     if (bos != null) { 
      try 
      { 
       bos.close(); 
      } catch (IOException ioe) 
      { 
       ioe.printStackTrace(); 
      } 
     } 
    } 
} 

错误从以下LogCatsee:

08-22 14:03:15.793: E/AndroidRuntime(773): FATAL EXCEPTION: main 
08-22 14:03:15.793: E/AndroidRuntime(773): android.os.NetworkOnMainThreadException 
08-22 14:03:15.793: E/AndroidRuntime(773): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117) 
08-22 14:03:15.793: E/AndroidRuntime(773): at java.net.InetAddress.lookupHostByName(InetAddress.java:385) 
08-22 14:03:15.793: E/AndroidRuntime(773): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236) 
08-22 14:03:15.793: E/AndroidRuntime(773): at java.net.InetAddress.getByName(InetAddress.java:289) 
08-22 14:03:15.793: E/AndroidRuntime(773): at java.net.InetSocketAddress.<init>(InetSocketAddress.java:105) 
08-22 14:03:15.793: E/AndroidRuntime(773): at java.net.InetSocketAddress.<init>(InetSocketAddress.java:90) 
08-22 14:03:15.793: E/AndroidRuntime(773): at libcore.net.url.FtpURLConnection.connectInternal(FtpURLConnection.java:219) 
08-22 14:03:15.793: E/AndroidRuntime(773): at libcore.net.url.FtpURLConnection.connect(FtpURLConnection.java:191) 
08-22 14:03:15.793: E/AndroidRuntime(773): at libcore.net.url.FtpURLConnection.getOutputStream(FtpURLConnection.java:339) 
08-22 14:03:15.793: E/AndroidRuntime(773): at de.noretec.nfcsync.view.Synchronisierung.uploadCsvAufServer(Synchronisierung.java:244) 
08-22 14:03:15.793: E/AndroidRuntime(773): at de.noretec.nfcsync.view.Synchronisierung$1.onClick(Synchronisierung.java:95) 
08-22 14:03:15.793: E/AndroidRuntime(773): at android.view.View.performClick(View.java:4204) 
08-22 14:03:15.793: E/AndroidRuntime(773): at android.view.View$PerformClick.run(View.java:17355) 
08-22 14:03:15.793: E/AndroidRuntime(773): at android.os.Handler.handleCallback(Handler.java:725) 
08-22 14:03:15.793: E/AndroidRuntime(773): at android.os.Handler.dispatchMessage(Handler.java:92) 
08-22 14:03:15.793: E/AndroidRuntime(773): at android.os.Looper.loop(Looper.java:137) 
08-22 14:03:15.793: E/AndroidRuntime(773): at android.app.ActivityThread.main(ActivityThread.java:5041) 
08-22 14:03:15.793: E/AndroidRuntime(773): at java.lang.reflect.Method.invokeNative(Native Method) 
08-22 14:03:15.793: E/AndroidRuntime(773): at java.lang.reflect.Method.invoke(Method.java:511) 
08-22 14:03:15.793: E/AndroidRuntime(773): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 
08-22 14:03:15.793: E/AndroidRuntime(773): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 
08-22 14:03:15.793: E/AndroidRuntime(773): at dalvik.system.NativeStart.main(Native Method) 
08-22 14:03:19.773: E/Trace(787): error opening trace file: No such file or directory (2) 

有谁知道为什么我得到了这些错误?

=======

UPDATE:

=======

正如你所说的,它是与android.os问题.NetworkOnMainThreadException。我无法在主(UI)线程中使用网络接口。所以我尝试了从AsyncTask <>扩展的单独的类。 现在我的应用程序不再崩溃,但会引发警告。

08-22 17:14:24.852: W/System.err(780): java.io.IOException: Unable to connect to server: Unable to retrieve file: 550 
08-22 17:14:24.870: W/System.err(780): at libcore.net.url.FtpURLConnection.connect(FtpURLConnection.java:203) 
08-22 17:14:24.870: W/System.err(780): at libcore.net.url.FtpURLConnection.getOutputStream(FtpURLConnection.java:339) 
08-22 17:14:24.870: W/System.err(780): at de.noretec.nfcsync.controller.FileUpload.doInBackground(FileUpload.java:40) 
08-22 17:14:24.870: W/System.err(780): at de.noretec.nfcsync.controller.FileUpload.doInBackground(FileUpload.java:1) 
08-22 17:14:24.878: W/System.err(780): at android.os.AsyncTask$2.call(AsyncTask.java:287) 
08-22 17:14:24.878: W/System.err(780): at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
08-22 17:14:24.878: W/System.err(780): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
08-22 17:14:24.878: W/System.err(780): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
08-22 17:14:24.878: W/System.err(780): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
08-22 17:14:24.878: W/System.err(780): at java.lang.Thread.run(Thread.java:856) 
08-22 17:14:26.148: W/System.err(780): java.io.IOException: Unable to connect to server: Unable to retrieve file: 550 
08-22 17:14:26.148: W/System.err(780): at libcore.net.url.FtpURLConnection.connect(FtpURLConnection.java:203) 
08-22 17:14:26.148: W/System.err(780): at libcore.net.url.FtpURLConnection.getOutputStream(FtpURLConnection.java:339) 
08-22 17:14:26.148: W/System.err(780): at de.noretec.nfcsync.controller.FileUpload.doInBackground(FileUpload.java:40) 
08-22 17:14:26.148: W/System.err(780): at de.noretec.nfcsync.controller.FileUpload.doInBackground(FileUpload.java:1) 
08-22 17:14:26.148: W/System.err(780): at android.os.AsyncTask$2.call(AsyncTask.java:287) 
08-22 17:14:26.148: W/System.err(780): at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
08-22 17:14:26.148: W/System.err(780): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 
08-22 17:14:26.148: W/System.err(780): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
08-22 17:14:26.148: W/System.err(780): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
08-22 17:14:26.148: W/System.err(780): at java.lang.Thread.run(Thread.java:856) 

做一个异步线程,我想我必须使用 保护无效doInBackground(字符串...为arg0)方法。

这是我的实际代码。我不确定我是否使用了正确的表格: public class FileUpload extends AsyncTask 我没有任何参数,但我可以使用一个。

public class FileUpload extends AsyncTask<String, Void, Void> { 

    @Override 
    protected Void doInBackground(String... arg0) { 
     Server server = new Server(); 
     StringBuffer sb = new StringBuffer("ftp://"); 

     sb.append(server.getBenutzer()); 
     sb.append(':'); 
     sb.append(server.getPasswort()); 
     sb.append('@'); 
     sb.append(server.getFtpServer()); 
     sb.append('/'); 
     sb.append(server.getPfadUndDateiName()); 
     sb.append(";type=a"); 

     BufferedInputStream bis = null; 
     BufferedOutputStream bos = null; 
     try { 
      URL url = new URL(sb.toString()); 
      URLConnection urlc = url.openConnection(); 

      bos = new BufferedOutputStream(urlc.getOutputStream()); 
      bis = new BufferedInputStream(new FileInputStream(server.getDateiName())); 

      int i; 
      // read byte by byte until end of stream 
      while ((i = bis.read()) != -1) 
      { 
       bos.write(i); 
      } 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (bis != null) { 
       try 
       { 
        bis.close(); 
       } catch (IOException ioe) 
       { 
        ioe.printStackTrace(); 
       } 
      } 
      if (bos != null) { 
       try 
       { 
        bos.close(); 
       } catch (IOException ioe) 
       { 
        ioe.printStackTrace(); 
       } 
      } 
     } 
     return null; 
    } 



    protected void onProgressUpdate(Integer... progress) { 

    } 



    protected void onPostExecute(Long result) { 

    } 
} 

=========

解决

=========

我使用的独立的类扩展来自AsyncTask。

我把它叫做:

new FTPFileUpload().execute(     
    server.getFtpServer(), 
    server.getBenutzer(), 
    server.getPasswort(), 
    Synchronisierung.this.notSyncedContent.toString(), 
    server.getPfadUndDateiName()); 

使用:

public class FTPFileUpload extends AsyncTask<String, Void, Void> { 

    @Override 
    protected Void doInBackground(String... params) { 
     FTPClient con = new FTPClient(); 
     try { 

      con.connect(InetAddress.getByName(params[0])); 

      if (con.login(params[1], params[2])) { 
       con.enterLocalPassiveMode(); 
       String data = params[3]; 
       ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes()); 
       boolean result = con.storeFile(params[4], in); 
       in.close(); 
       // if (result) 
       // System.out.println("upload result: " + result); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     try { 
      con.logout(); 
      con.disconnect(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 
} 
+0

-1您是否尝试向Google寻求例外情况? – Selvin

+0

向上投票的问题,因为它的解决方案帮助我的12-13小时的斗争。谢谢! – CodeIt

回答

0

尝试使用Apache公地净FTP库。

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.PrintWriter; 

import org.apache.commons.net.PrintCommandListener; 
import org.apache.commons.net.ftp.FTP; 
import org.apache.commons.net.ftp.FTPClient; 
import org.apache.commons.net.ftp.FTPReply; 

public class FTPUploader { 

    FTPClient ftp = null; 

    public FTPUploader(String host, String user, String pwd) throws Exception{ 
     ftp = new FTPClient(); 
     ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); 
     int reply; 
     ftp.connect(host); 
     reply = ftp.getReplyCode(); 
     if (!FTPReply.isPositiveCompletion(reply)) { 
      ftp.disconnect(); 
      throw new Exception("Exception in connecting to FTP Server"); 
     } 
     ftp.login(user, pwd); 
     ftp.setFileType(FTP.BINARY_FILE_TYPE); 
     ftp.enterLocalPassiveMode(); 
    } 
    public void uploadFile(String localFileFullName, String fileName, String hostDir) 
      throws Exception { 
     try(InputStream input = new FileInputStream(new File(localFileFullName))){ 
     this.ftp.storeFile(hostDir + fileName, input); 
     } 
    } 

    public void disconnect(){ 
     if (this.ftp.isConnected()) { 
      try { 
       this.ftp.logout(); 
       this.ftp.disconnect(); 
      } catch (IOException f) { 
       // do nothing as file is already saved to server 
      } 
     } 
    } 

更新:

尝试使用您的代码,因为在Android版本低于gingerbread更大的线程或服务的OS不允许你这样做让你网络的UI主线程所以这Exception上已发生

android.os.NetworkOnMainThreadException 

进一步阅读到这个site.

更新:

尝试改变这一行

sb.append(";type=a"); 

sb.append(";type=i"); 
+0

我试过使用AsyncTask。但还有其他警告,请参阅下面我的更新。我不确定我是否使用了doInBackground()的正确语法方法。我没有任何参数,但我可以给一个参数。 – squietschi

+0

嘿看到我的新编辑: – Prakhar

+0

我将类型从a更改为i。没有改变。 – squietschi

0

08-22 14:03:15.793:E/AndroidRuntime(773):致命异常: main 08-22 14:03:15.793:E/AndroidRuntime(773):android.os.NetworkOnMainThreadException

问题来自2.x + android版本,因此您无法执行网络操作,因为您阻止了主UI线程。您应该使用AsynTask非常适合这种操作。或者你创建一个FileTransferThread类。

+0

我试过使用AsyncTask。但还有其他警告,请参阅下面我的更新。我不确定我是否使用了doInBackground()的正确语法方法。我没有任何参数,但我可以给一个参数。 – squietschi