All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.orion.net.host.sftp.SftpExecutor Maven / Gradle / Ivy

The newest version!
package com.orion.net.host.sftp;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.orion.lang.constant.Const;
import com.orion.lang.define.StreamEntry;
import com.orion.lang.utils.Charsets;
import com.orion.lang.utils.Exceptions;
import com.orion.lang.utils.io.Files1;
import com.orion.lang.utils.io.Streams;
import com.orion.net.host.HostConnector;
import com.orion.net.host.sftp.transfer.SftpDownloader;
import com.orion.net.host.sftp.transfer.SftpUploader;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Vector;

/**
 * sftp 执行器
 * 

* 文件路必须是绝对路径 可以包含 ../ ./ * * @author Jiahang Li * @version 1.0.0 * @since 2022/5/18 15:22 */ public class SftpExecutor extends BaseSftpExecutor implements HostConnector { private final ChannelSftp channel; public SftpExecutor(ChannelSftp channel) { this(channel, Const.UTF_8); } public SftpExecutor(ChannelSftp channel, String charset) { this.channel = channel; this.charset = charset; } @Override public void bufferSize(int bufferSize) { this.bufferSize = bufferSize; } @Override public void charset(String charset) { try { channel.setFilenameEncoding(Charsets.of(charset)); this.charset = charset; } catch (Exception e) { throw Exceptions.sftp("set sftp charset error", e); } } @Override public void sendSignal(String signal) { try { channel.sendSignal(signal); } catch (Exception e) { throw Exceptions.ioRuntime(e); } } @Override public String getHome() { try { return channel.getHome(); } catch (SftpException e) { throw Exceptions.sftp(e); } } @Override public boolean isExist(String path) { try { return channel.lstat(path) != null; } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return false; } throw Exceptions.sftp(e); } } @Override public String getPath(String path) { try { return channel.realpath(path); } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return null; } throw Exceptions.sftp(e); } } @Override public String getLinkPath(String path) { try { return channel.readlink(path); } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return null; } else if (SftpErrorMessage.BAD_MESSAGE.isCause(e)) { return null; } else { throw Exceptions.sftp(e); } } } @Override public SftpFile getFile(String path) { return this.getFile(path, false); } @Override public SftpFile getFile(String path, boolean followSymbolic) { try { SftpATTRS attr; if (followSymbolic) { attr = channel.stat(path); } else { attr = channel.lstat(path); } return new SftpFileWrapper(path, attr); } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return null; } else { throw Exceptions.sftp(e); } } } @Override public long getSize(String path) { SftpFile file = this.getFile(path, false); if (file == null) { return -1; } return file.getSize(); } @Override public void setFileAttribute(SftpFile attribute) { try { channel.setStat(attribute.getPath(), ((SftpFileWrapper) attribute).getAttrs()); } catch (Exception e) { throw Exceptions.sftp(e); } } @Override public void setModifyTime(String path, Date date) { try { channel.setMtime(path, (int) (date.getTime() / Const.MS_S_1)); } catch (Exception e) { throw Exceptions.sftp(e); } } @Override public void changeMode(String file, int permission) { try { channel.chmod(Files1.permission10to8(permission), file); } catch (Exception e) { throw Exceptions.sftp(e); } } @Override public void changeOwner(String file, int uid) { try { channel.chown(uid, file); } catch (Exception e) { throw Exceptions.sftp(e); } } @Override public void changeGroup(String file, int gid) { try { channel.chgrp(gid, file); } catch (Exception e) { throw Exceptions.sftp(e); } } @Override public void makeDirectory(String path) { try { channel.mkdir(path); } catch (SftpException e) { throw Exceptions.sftp(e); } } @Override public void removeDir(String path) { try { channel.rmdir(path); } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return; } throw Exceptions.sftp(e); } } @Override public void removeFile(String path) { try { channel.rm(path); } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return; } throw Exceptions.sftp(e); } } @Override public void touch(String path) { this.touch(path, false); } @Override public void touchTruncate(String path) { this.touch(path, true); } @Override public void touch(String path, boolean truncate) { OutputStream out = null; try { if (truncate) { out = this.openOutputStream(path, 0); } else { out = this.openOutputStream(path, 1); } out.flush(); } catch (Exception e) { throw Exceptions.sftp(e); } finally { Streams.close(out); } } @Override public void truncate(String path) { try { this.touchTruncate(path); } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return; } throw Exceptions.sftp(e); } } @Override public void hardLink(String source, String target) { this.link(source, target, true); } @Override public void symLink(String source, String target) { this.link(source, target, false); } @Override public void link(String source, String target, boolean hard) { try { // 检查是否需要创建目标文件目录 if (!this.isSameParentPath(source, target)) { this.makeDirectories(Files1.getParentPath(target)); } if (hard) { channel.hardlink(source, target); } else { channel.symlink(source, target); } } catch (Exception e) { throw Exceptions.sftp(e); } } @Override protected void doMove(String source, String target) { try { channel.rename(source, target); } catch (Exception e) { throw Exceptions.sftp(e); } } // -------------------- open -------------------- @Override public InputStream openInputStream(String path, long skip) throws IOException { try { return channel.get(path, null, skip); } catch (Exception e) { throw Exceptions.io("could open file input stream " + path, e); } } @Override public OutputStream openOutputStream(String path, boolean append) throws IOException { if (append) { return this.openOutputStream(path, 2); } else { return this.openOutputStream(path, 0); } } /** * 打开存在文件的输出流 * * @param path 文件路径 * @param mode 0 完全覆盖模式 * 1 恢复模式 * 2 追加模式 * @return OutputStream * @throws IOException IOException */ public OutputStream openOutputStream(String path, int mode) throws IOException { try { this.makeDirectories(Files1.getParentPath(path)); return channel.put(path, mode); } catch (Exception e) { throw Exceptions.io("could open file output stream " + path, e); } } // -------------------- read -------------------- @Override public int read(String path, long skip, byte[] bs, int offset, int len) throws IOException { InputStream in = null; try { in = this.openInputStream(path, skip); return in.read(bs, offset, len); } finally { Streams.close(in); } } // -------------------- write -------------------- @Override protected long doTransfer(String path, OutputStream out, long skip, int size, boolean close) throws IOException { long r = 0; byte[] bs = new byte[bufferSize]; InputStream in = null; try { in = this.openInputStream(path, skip); if (size != -1) { boolean mod = size % bufferSize == 0; long readTimes = size / bufferSize; if (mod || readTimes == 0) { readTimes++; } for (int i = 0; i < readTimes; i++) { if (readTimes == 1) { int read = in.read(bs, 0, size); out.write(bs, 0, read); r += read; } else { int read = in.read(bs, 0, bufferSize); if (read != -1) { out.write(bs, 0, read); r += read; } else { break; } } } } else { int read; while ((read = in.read(bs, 0, bufferSize)) != -1) { out.write(bs, 0, read); r += read; } } } finally { Streams.close(in); if (close) { Streams.close(out); } } return r; } @Override protected void doWrite(String path, InputStream in, StreamEntry entry) throws IOException { this.write(path, in, entry, 0); } @Override protected void doAppend(String path, InputStream in, StreamEntry entry) throws IOException { this.write(path, in, entry, 2); } /** * 拼接/写入到文件 * * @param path 文件绝对路径 * @param in 输入流 * @param entry 写入信息 * @param mode 0 完全覆盖模式 * 1 恢复模式 如果文件正在传输时, 由于网络等原因导致传输中断, 则下一次传输相同的文件, 会从上一次中断的地方续传 * 2 追加模式 * @throws IOException IOException */ private void write(String path, InputStream in, StreamEntry entry, int mode) throws IOException { this.touch(path, mode == 0); OutputStream out = null; try { out = this.openOutputStream(path, mode); if (in != null) { byte[] bs = new byte[bufferSize]; int read; while ((read = in.read(bs)) != -1) { out.write(bs, 0, read); } } else if (entry != null) { out.write(entry.getBytes(), entry.getOff(), entry.getLen()); } out.flush(); } finally { Streams.close(out); } } // -------------------- bigfile -------------------- @Override public SftpUploader upload(String remote, File local) { return new SftpUploader(this, remote, local); } @Override public SftpUploader upload(String remote, String local) { return new SftpUploader(this, remote, local); } @Override public SftpDownloader download(String remote, File local) { return new SftpDownloader(this, remote, local); } @Override public SftpDownloader download(String remote, String local) { return new SftpDownloader(this, remote, local); } // -------------------- list -------------------- @Override public List list(String path) { List list = new ArrayList<>(); try { // 检查是否为目录 SftpATTRS stat = channel.stat(path); if (!stat.isDir()) { return new ArrayList<>(); } // 查询列表 Vector files = channel.ls(path); for (Object file : files) { ChannelSftp.LsEntry entity = (ChannelSftp.LsEntry) file; String filename = entity.getFilename(); if (".".equals(filename) || "..".equals(filename)) { continue; } list.add(new SftpFileWrapper(Files1.getPath(path, filename), entity.getAttrs())); } } catch (Exception e) { if (SftpErrorMessage.NO_SUCH_FILE.isCause(e)) { return new ArrayList<>(); } throw Exceptions.sftp(e); } return list; } @Override public void connect() { try { channel.connect(); } catch (Exception e) { throw Exceptions.connection(e); } this.charset(charset); } @Override public void connect(int timeout) { try { channel.connect(timeout); } catch (Exception e) { throw Exceptions.connection(e); } this.charset(charset); } @Override public boolean isConnected() { return channel.isConnected(); } @Override public int getServerVersion() { try { return channel.getServerVersion(); } catch (SftpException e) { throw Exceptions.sftp(e); } } @Override public void close() { channel.disconnect(); } @Override public ChannelSftp getChannel() { return channel; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy