使用 SSH 将文件从 android 应用程序发送到 raspberry pi
Sending a file from android application to raspberry pi using SSH
我正在尝试通过 WIFI 从 android 应用程序向 RaspberryPi 发送文件。
我可以连接到 RPI 并通过 SSH 向它发送命令。
这是我用来发送 ssh 命令的函数:
public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
ChannelExec channelssh = (ChannelExec)
session.openChannel("exec");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channelssh.setOutputStream(baos);
// Execute command
channelssh.setCommand("scp " + file + " " + username + "@" + hostname + ":/home/pi/Desktop");
channelssh.connect();
try{Thread.sleep(5000);}catch(Exception ee){}
channelssh.disconnect();
return baos.toString();
}
这是要发送的 SSH 命令
scp /storage/emulated/0/Download/201906071017.txt pi@192.168.4.1:/home/pi/Desktop
我在 windows 终端上尝试 运行 SSH 命令并成功上传文件
编辑:
我在 .connect()
和 .disconnect()
之间添加了这段代码,以等待我收到命令的响应以断开与 RPi 的连接
channelssh.setErrStream(System.err);
InputStream in=channelssh.getInputStream();
channelssh.connect();
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channelssh.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channelssh.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channelssh.disconnect();
现在我的权限在日志中被拒绝,用户名和密码是正确的。
W/System.err: Permission denied, please try again.
W/System.err: Permission denied, please try again.
W/System.err: Permission denied (publickey,password).
W/System.err: lost connection
I/System.out: exit-status: 1
我做到了!!
我最终使用 sftp 服务上传文件
我正在使用 ChannelSsh
和 ChannelExec
。我应该使用 ChannelSftp
这是工作代码
package com.example.a.sitetool;
import android.util.Log;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
public class RpiUpdate {
public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
throws Exception {
Log.d("MainActivity", "Entered executeRemoteCommand");
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp channelsftp = (ChannelSftp) channel;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channelsftp.cd("/home/pi/Desktop");
channelsftp.put(new FileInputStream(file), file.getName());
channelsftp.setOutputStream(baos);
// Execute command
channelsftp.put(file.getName(),"/home/pi/Desktop");
InputStream in=channelsftp.getInputStream();
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channelsftp.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channelsftp.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
return baos.toString();
}
}
编辑:
我优化了代码并删除了 ByteArrayOutputStream
,因为 Channelsftp
不需要它。此更改导致 return 变为 void
而不是 String
我还添加了更改输出文件权限的功能。
package com.example.a.sitetool;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;
public class RpiUpdate {
private static boolean success;
public static void update() {
//TODO add online version checking and download
if (success)
uploadFile();
}
private static void uploadFile() {
Log.d("RPIUpdate", "Entered upload File");
success=false;
new AsyncTask<Integer, Void, Void>() {
@Override
protected Void doInBackground(Integer... params) {
try {
executeRemoteCommand("pi", "rbs", "192.168.4.1", 22);
Log.d("MainActivity", "File Uploaded");
success = true;
} catch (Exception e) {
e.printStackTrace();
Log.d("MainActivity", "Failed to upload file");
success = false;
}
return null;
}
}.execute(1);
}
public static void executeRemoteCommand(final String username, final String password, final String hostname, final int port)
throws Exception {
Log.d("RPiUpdate", "Entered executeRemoteCommand");
//Creating the path on android to bbserver.py
File root;
root = new File(Environment.getExternalStorageDirectory() + File.separator + "Download");
if (!root.exists()) {
root.mkdirs();
}
File file = new File(root, "bbserver.py");
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
//SFTP setup
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp channelsftp = (ChannelSftp) channel;
//Renaming the old bbserver.py
SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd:HH:mm", Locale.ENGLISH);
Date now = new Date();
channelsftp.cd("/home/pi/Desktop");
// 384 in octal is 600. This makes the file non executable. only readable and writable
channelsftp.chmod(384, "/home/pi/Desktop/bbserver.py");
channelsftp.rename("/home/pi/Desktop/bbserver.py", "/home/pi/Desktop/bbserver" + formatter.format(now) + ".py");
//sending the new bbserver.py file
channelsftp.put(new FileInputStream(file), file.getName());
Log.d("RPiUpdate", "Sent file");
//511 in octal is 777. This gives the file all available permissions(read, write, execute). thus making the file an executable
channelsftp.chmod(511, "/home/pi/Desktop/" + file.getName());
Log.d("RPiUpdate", "Changed permissions");
channel.disconnect();
}
我正在尝试通过 WIFI 从 android 应用程序向 RaspberryPi 发送文件。
我可以连接到 RPI 并通过 SSH 向它发送命令。
这是我用来发送 ssh 命令的函数:
public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
ChannelExec channelssh = (ChannelExec)
session.openChannel("exec");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channelssh.setOutputStream(baos);
// Execute command
channelssh.setCommand("scp " + file + " " + username + "@" + hostname + ":/home/pi/Desktop");
channelssh.connect();
try{Thread.sleep(5000);}catch(Exception ee){}
channelssh.disconnect();
return baos.toString();
}
这是要发送的 SSH 命令
scp /storage/emulated/0/Download/201906071017.txt pi@192.168.4.1:/home/pi/Desktop
我在 windows 终端上尝试 运行 SSH 命令并成功上传文件
编辑:
我在 .connect()
和 .disconnect()
之间添加了这段代码,以等待我收到命令的响应以断开与 RPi 的连接
channelssh.setErrStream(System.err);
InputStream in=channelssh.getInputStream();
channelssh.connect();
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channelssh.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channelssh.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channelssh.disconnect();
现在我的权限在日志中被拒绝,用户名和密码是正确的。
W/System.err: Permission denied, please try again.
W/System.err: Permission denied, please try again.
W/System.err: Permission denied (publickey,password).
W/System.err: lost connection
I/System.out: exit-status: 1
我做到了!!
我最终使用 sftp 服务上传文件
我正在使用 ChannelSsh
和 ChannelExec
。我应该使用 ChannelSftp
这是工作代码
package com.example.a.sitetool;
import android.util.Log;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
public class RpiUpdate {
public static String executeRemoteCommand(final String username, final String password, final String hostname, final int port, final File file)
throws Exception {
Log.d("MainActivity", "Entered executeRemoteCommand");
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
// SSH Channel
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp channelsftp = (ChannelSftp) channel;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
channelsftp.cd("/home/pi/Desktop");
channelsftp.put(new FileInputStream(file), file.getName());
channelsftp.setOutputStream(baos);
// Execute command
channelsftp.put(file.getName(),"/home/pi/Desktop");
InputStream in=channelsftp.getInputStream();
byte[] tmp=new byte[1024];
while(true){
while(in.available()>0){
int i=in.read(tmp, 0, 1024);
if(i<0)break;
System.out.print(new String(tmp, 0, i));
}
if(channelsftp.isClosed()){
if(in.available()>0) continue;
System.out.println("exit-status: "+channelsftp.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
channel.disconnect();
return baos.toString();
}
}
编辑:
我优化了代码并删除了 ByteArrayOutputStream
,因为 Channelsftp
不需要它。此更改导致 return 变为 void
而不是 String
我还添加了更改输出文件权限的功能。
package com.example.a.sitetool;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Properties;
public class RpiUpdate {
private static boolean success;
public static void update() {
//TODO add online version checking and download
if (success)
uploadFile();
}
private static void uploadFile() {
Log.d("RPIUpdate", "Entered upload File");
success=false;
new AsyncTask<Integer, Void, Void>() {
@Override
protected Void doInBackground(Integer... params) {
try {
executeRemoteCommand("pi", "rbs", "192.168.4.1", 22);
Log.d("MainActivity", "File Uploaded");
success = true;
} catch (Exception e) {
e.printStackTrace();
Log.d("MainActivity", "Failed to upload file");
success = false;
}
return null;
}
}.execute(1);
}
public static void executeRemoteCommand(final String username, final String password, final String hostname, final int port)
throws Exception {
Log.d("RPiUpdate", "Entered executeRemoteCommand");
//Creating the path on android to bbserver.py
File root;
root = new File(Environment.getExternalStorageDirectory() + File.separator + "Download");
if (!root.exists()) {
root.mkdirs();
}
File file = new File(root, "bbserver.py");
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostname, port);
session.setPassword(password);
// Avoid asking for key confirmation
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "no");
session.setConfig(prop);
session.connect();
//SFTP setup
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp channelsftp = (ChannelSftp) channel;
//Renaming the old bbserver.py
SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd:HH:mm", Locale.ENGLISH);
Date now = new Date();
channelsftp.cd("/home/pi/Desktop");
// 384 in octal is 600. This makes the file non executable. only readable and writable
channelsftp.chmod(384, "/home/pi/Desktop/bbserver.py");
channelsftp.rename("/home/pi/Desktop/bbserver.py", "/home/pi/Desktop/bbserver" + formatter.format(now) + ".py");
//sending the new bbserver.py file
channelsftp.put(new FileInputStream(file), file.getName());
Log.d("RPiUpdate", "Sent file");
//511 in octal is 777. This gives the file all available permissions(read, write, execute). thus making the file an executable
channelsftp.chmod(511, "/home/pi/Desktop/" + file.getName());
Log.d("RPiUpdate", "Changed permissions");
channel.disconnect();
}