2019年5月2日木曜日

JAVA JSch SFTP AndroidクライアントからSSHサーバーへのファイル転送

2019 May. 03.
2019 May. 02.

https://qiita.com/nenokido2000/items/a00348c9f6a0f942773b より




MainActivity.java

  1. package YOUR.PACKAGE.NAME;
  2. import android.support.v7.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. import android.widget.Button;
  6. import android.widget.TextView;
  7.  
  8. public class MainActivity extends AppCompatActivity {
  9.  
  10.  
  11. /** Channel接続タイプ */
  12. private static final String CHANNEL_TYPE = "sftp";
  13.  
  14. private MyTask task;
  15.  
  16. @Override
  17. protected void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19.  
  20. setContentView(R.layout.activity_main);
  21.  
  22. /*
  23. final String ServerIP = "ServerIP";
  24. final int Port = PortNum;
  25. final String UserId = "USER";
  26. final String PassPhrase = "YOURPASSPHRASE";
  27. final String IdentityKeyPath = "YOUR/SECRET/FILE/PATH"; // Do not attach '/' at head of path
  28. final String SourcePath = "PATH/TO/SOURCE/FILE"; // Do not attach '/' at head of path
  29. final String DestPath = "PATH/TO/DEST/FILE";
  30. */
  31.  
  32. final String ServerIP="";
  33. final int Port = ;
  34. final String UserId = "";
  35. final String PassPhrase = "";
  36. final String IdentityKeyPath = "";
  37. final String SourcePath = "";
  38. final String DestPath = "";
  39.  
  40. Button button1= (Button) findViewById(R.id.button1);
  41. TextView textView1 = (TextView) findViewById(R.id.textView1);
  42.  
  43. // タスクの生成
  44. task = new MyTask(ServerIP, Port, UserId, PassPhrase, IdentityKeyPath, SourcePath, DestPath,this);
  45.  
  46. button1.setOnClickListener(new View.OnClickListener() {
  47. @Override
  48. public void onClick(View v) {
  49. v.setEnabled(false);
  50. // 非同期処理を開始する
  51. task.execute();
  52. }
  53. });
  54. }
  55. }


MyTask.java
  1. package YOUR.PACKAGE.NAME;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.os.AsyncTask;
  5. import android.widget.TextView;
  6.  
  7. import com.jcraft.jsch.JSchException;
  8.  
  9. import java.lang.ref.WeakReference;
  10.  
  11. public class MyTask extends AsyncTask {
  12. private final String ServerIp;
  13. private final int Port;
  14. private final String User;
  15. private final String IdentityKeyPath;
  16. private final String PassPhrase;
  17. private final String SrcPath;
  18. private final String DestPath;
  19. private WeakReference weakReference;
  20. // constructor
  21. MyTask(final String ServerIp, final int Port, final String User,
  22. final String PassPhrase, final String IdentityKeyPath, final String SrcPath,
  23. final String DestPath, Context referenceContext) {
  24. super();
  25. // 呼び出し元へのweakReference
  26. weakReference = new WeakReference<>(referenceContext);
  27. this.ServerIp = ServerIp;
  28. this.Port = Port;
  29. this.User = User;
  30. this.PassPhrase = PassPhrase;
  31. this.IdentityKeyPath = IdentityKeyPath;
  32. this.SrcPath = SrcPath;
  33. this.DestPath = DestPath;
  34. }
  35. /**
  36. * バックグランドで行う処理
  37. */
  38. @Override
  39. protected String doInBackground(Void... value) {
  40. // startJsch
  41. MyJsch mJsch = new MyJsch( ServerIp, Port, User, PassPhrase, IdentityKeyPath, SrcPath,
  42. DestPath, weakReference.get());
  43. try {
  44. mJsch.putFile();
  45. } catch (JSchException e) {
  46. e.printStackTrace();
  47. return e.toString();
  48. }
  49. return "Success";
  50. }
  51. /**
  52. * バックグランド処理が完了し、UIスレッドに反映する
  53. */
  54. @Override
  55. protected void onPostExecute(String result) {
  56. // get a reference to the activity if it is still there
  57. Activity activity = (Activity) weakReference.get();
  58. if (activity == null || activity.isFinishing()) return;
  59. activity.findViewById(R.id.button1).setEnabled(true);
  60. TextView tv = activity.findViewById(R.id.textView1);
  61. tv.setText(result);
  62. }
  63. }


MyJsch.java
  1. package YOUR.PACKAGE.NAME;
  2. import android.content.Context;
  3. import android.util.Log;
  4.  
  5. import com.jcraft.jsch.Channel;
  6. import com.jcraft.jsch.ChannelSftp;
  7. import com.jcraft.jsch.JSch;
  8. import com.jcraft.jsch.JSchException;
  9. import com.jcraft.jsch.Session;
  10. import com.jcraft.jsch.SftpException;
  11. import com.jcraft.jsch.UserInfo;
  12.  
  13. import java.io.File;
  14. import java.util.Collections;
  15. import java.util.List;
  16.  
  17. public class MyJsch {
  18. private final String ServerIp;
  19. private final int Port;
  20. private final String User;
  21. private final String PassPhrase;
  22. private final String IdentityKeyPath;
  23. private final String SrcPath;
  24. private final String DestPath;
  25. private Context activityContext;
  26.  
  27. private String externalPath;
  28.  
  29. /** Channel接続タイプ */
  30. private static final String CHANNEL_TYPE = "sftp";
  31.  
  32. /**
  33. * コンストラクタ
  34. */
  35. MyJsch(final String ServerIp, final int Port, final String User, final String PassPhrase,
  36. final String IdentityKeyPath, final String SrcPath, final String DestPath,
  37. Context activityContext) {
  38. this.ServerIp = ServerIp;
  39. this.Port = Port;
  40. this.User = User;
  41. this.IdentityKeyPath = IdentityKeyPath;
  42. this.PassPhrase = PassPhrase;
  43. this.SrcPath = SrcPath;
  44. this.DestPath = DestPath;
  45. this.activityContext = activityContext;
  46. }
  47.  
  48.  
  49. /**
  50. * ファイルアップロード
  51. *
  52. * @throws JSchException
  53. * Session・Channelの設定/接続エラー時に発生
  54. */
  55. public void putFile()
  56. throws JSchException {
  57.  
  58. Session session = null;
  59. ChannelSftp channel = null;
  60.  
  61.  
  62. // 外部ストーリッジ確認
  63. List sdCardFilesDirPaths =
  64. SdCardDirPaths.getSdCardFilesDirPathListForLollipop( activityContext );
  65. Collections.sort(sdCardFilesDirPaths, new CompStringLength());
  66. for (String p : sdCardFilesDirPaths) {
  67. Log.d("My", "SDパスの1つ: " + p);
  68. }
  69. externalPath = sdCardFilesDirPaths.get(0);
  70. externalPath = externalPath.replaceAll("/Android.*$", "");
  71. Log.d("My", "SDパス: " + externalPath);
  72. // get sourcePath
  73. final String sourcePath = externalPath + "/" + SrcPath;
  74. Log.d("My", "sourcePath " + sourcePath );
  75. if ( new File(sourcePath).exists()) {
  76. Log.d("My", sourcePath + " exists.");
  77. } else {
  78. Log.d("My", sourcePath + " not exist.");
  79. }
  80. /*
  81. * sftp通信を実行
  82. */
  83. try {
  84. session = connectSession();
  85. channel = connectChannelSftp(session);
  86. String absoluteDestPath = channel.getHome() + "/" + DestPath;
  87. String destFile = new File(absoluteDestPath).getName();
  88. int numDestPath = absoluteDestPath.length();
  89. int numDestFile = destFile.length();
  90. String destParentPath = absoluteDestPath.substring( 0, numDestPath - numDestFile );
  91. Log.d("My", "absoluteDestPath is " + absoluteDestPath);
  92. Log.d("My", "destFile is " + destFile);
  93. Log.d("My", "destParentPath is " + destParentPath);
  94. Log.d("My", "current local directory is " + channel.lpwd());
  95. Log.d("My", "remote home directory is " + channel.getHome());
  96. channel.cd(destParentPath);
  97. channel.put(sourcePath, destFile);
  98. try {
  99. channel.lstat(destFile);
  100. } catch (SftpException e) {
  101. Log.d("My", DestPath + " does not exist.");
  102. Log.d("My", e.toString());
  103. }
  104. } catch (SftpException e) {
  105. Log.d("My",e.toString());
  106. } finally {
  107. disconnect(session, channel);
  108. }
  109. }
  110. /**
  111. * Sessionを開始
  112. */
  113. private Session connectSession()
  114. throws JSchException {
  115. final JSch jsch = new JSch();
  116. // 鍵追加
  117. String keyFilePath = externalPath + "/" + IdentityKeyPath;
  118. if ( new File(keyFilePath).exists()) {
  119. Log.d("My", keyFilePath + " exists.");
  120. } else {
  121. Log.d("My", keyFilePath + " not exist.");
  122. }
  123. jsch.addIdentity(keyFilePath, PassPhrase);
  124. // Session設定
  125. final Session session = jsch.getSession(User, ServerIp, Port);
  126. final UserInfo userInfo = new SftpUserInfo();
  127. // TODO 今回は使用しないがパスフレーズ等が必要な場合はUserInfoインスタンス経由で設定する
  128. session.setUserInfo(userInfo);
  129. session.connect();
  130. return session;
  131. }
  132. /**
  133. * SFTPのChannelを開始
  134. *
  135. * @param session
  136. * 開始されたSession情報
  137. */
  138. private ChannelSftp connectChannelSftp(final Session session)
  139. throws JSchException {
  140. final ChannelSftp channel = (ChannelSftp) session.openChannel(CHANNEL_TYPE);
  141. try {
  142. channel.connect();
  143. } catch (JSchException e) {
  144. Log.d("My", e.toString());
  145. }
  146. return channel;
  147. }
  148. /**
  149. * Session・Channelの終了
  150. *
  151. * @param session
  152. * 開始されたSession情報
  153. * @param channels
  154. * 開始されたChannel情報.複数指定可能
  155. */
  156. private void disconnect(final Session session, final Channel... channels) {
  157. if (channels != null) {
  158. for (Channel c: channels ) {
  159. if (c != null) {
  160. c.disconnect();
  161. }
  162. }
  163. }
  164. if (session != null) {
  165. session.disconnect();
  166. }
  167. }
  168. /**
  169. * SFTPに接続するユーザ情報を保持するクラス
  170. */
  171. private static class SftpUserInfo implements UserInfo {
  172. @Override
  173. public String getPassword() {
  174. return null;
  175. }
  176. @Override
  177. public boolean promptPassword(String arg0) {
  178. return true;
  179. }
  180. @Override
  181. public boolean promptPassphrase(String arg0) {
  182. return true;
  183. }
  184. @Override
  185. public boolean promptYesNo(String arg0) {
  186. return true;
  187. }
  188. @Override
  189. public void showMessage(String arg0) {
  190. }
  191. @Override
  192. public String getPassphrase() {
  193. return null;
  194. }
  195. }
  196. }

0 件のコメント:

コメントを投稿