基于JSch的Sftp工具类

时间:2021-08-22 07:40:23

本Sftp工具类的API如下所示。

1)构造方法摘要

Sftp(String host, int port, int timeout, String username, String password)

参数:

host - SFTP服务器IP地址

port - SFTP服务器端口

timeout - 连接超时时间,单位毫秒

username - 用户名

password - 密码

2)方法摘要

boolean
changeDir(String pathName)
          切换工作目录
boolean changeToHomeDir()
          切换到根目录
boolean changeToParentDir()
          切换到上一级目录
String currentDir()
          当前工作目录
boolean delDir(String dirName)
          删除文件夹
boolean delFile(String fileName)
          删除文件
boolean downloadFile(String remotePath, String fileName,String localPath)
          下载文件
boolean exist(String name)
          当前目录是否存在文件或文件夹
boolean exist(String path, String name)
          指定目录下,是否存在文件或文件夹
boolean existDir(String name)
          当前目录是否存在文件夹
boolean existDir(String path, String name)
          指定目录下,是否存在文件夹
boolean existFile(String name)
          当前目录是否存在文件
boolean existFile(String path, String name)
          指定目录下,是否存在文件
boolean login()
          登陆SFTP服务器
void logout()
          登出
String[] ls()
          当前目录下文件及文件夹名称列表
String[] ls(String pathName)
          指定目录下文件及文件夹名称列表
String[] lsDirs()
          当前目录下文件夹名称列表
String[] lsDirs(String pathName)
          指定目录下文件夹名称列表
String[] lsFiles()
          当前目录下文件名称列表
String[] lsFiles(String pathName)
          指定目录下文件名称列表
boolean makeDir(String dirName)
          创建目录
boolean uploadFile(String pathName,String fileName,InputStream input)
          上传文件
boolean uploadFile(String pathName, String fileName, String localFile)
          上传文件

3)源代码

 import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import org.apache.log4j.Logger;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.ChannelSftp.LsEntry; /**
* SFTP(Secure File Transfer Protocol),安全文件传送协议。
* @version 1.0 2014/12/18
* @author dongliyang
*/
public class Sftp { /** 日志记录器 */
private Logger logger = Logger.getLogger(Sftp.class);
/** Session */
private Session session = null;
/** Channel */
private ChannelSftp channel = null;
/** SFTP服务器IP地址 */
private String host;
/** SFTP服务器端口 */
private int port;
/** 连接超时时间,单位毫秒 */
private int timeout; /** 用户名 */
private String username;
/** 密码 */
private String password; /**
* SFTP 安全文件传送协议
* @param host SFTP服务器IP地址
* @param port SFTP服务器端口
* @param timeout 连接超时时间,单位毫秒
* @param username 用户名
* @param password 密码
*/
public Sftp(String host,int port,int timeout,String username,String password){
this.host = host;
this.port = port;
this.timeout = timeout;
this.username = username;
this.password = password;
} /**
* 登陆SFTP服务器
* @return boolean
*/
public boolean login() { try {
JSch jsch = new JSch();
session = jsch.getSession(username, host, port);
if(password != null){
session.setPassword(password);
}
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(timeout);
session.connect();
logger.debug("sftp session connected"); logger.debug("opening channel");
channel = (ChannelSftp)session.openChannel("sftp");
channel.connect(); logger.debug("connected successfully");
return true;
} catch (JSchException e) {
logger.error("sftp login failed",e);
return false;
}
} /**
* 上传文件
* <p>
* 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/
* <table border="1">
* <tr><td>当前目录</td><td>方法</td><td>参数:绝对路径/相对路径</td><td>上传后</td></tr>
* <tr><td>/</td><td>uploadFile("testA","upload.txt",new FileInputStream(new File("up.txt")))</td><td>相对路径</td><td>/testA/upload.txt</td></tr>
* <tr><td>/</td><td>uploadFile("testA/testA_B","upload.txt",new FileInputStream(new File("up.txt")))</td><td>相对路径</td><td>/testA/testA_B/upload.txt</td></tr>
* <tr><td>/</td><td>uploadFile("/testA/testA_B","upload.txt",new FileInputStream(new File("up.txt")))</td><td>绝对路径</td><td>/testA/testA_B/upload.txt</td></tr>
* </table>
* </p>
* @param pathName SFTP服务器目录
* @param fileName 服务器上保存的文件名
* @param input 输入文件流
* @return boolean
*/
public boolean uploadFile(String pathName,String fileName,InputStream input){ String currentDir = currentDir();
if(!changeDir(pathName)){
return false;
} try {
channel.put(input,fileName,ChannelSftp.OVERWRITE);
if(!existFile(fileName)){
logger.debug("upload failed");
return false;
}
logger.debug("upload successful");
return true;
} catch (SftpException e) {
logger.error("upload failed",e);
return false;
} finally {
changeDir(currentDir);
}
} /**
* 上传文件
* <p>
* 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/
* <table border="1">
* <tr><td>当前目录</td><td>方法</td><td>参数:绝对路径/相对路径</td><td>上传后</td></tr>
* <tr><td>/</td><td>uploadFile("testA","upload.txt","up.txt")</td><td>相对路径</td><td>/testA/upload.txt</td></tr>
* <tr><td>/</td><td>uploadFile("testA/testA_B","upload.txt","up.txt")</td><td>相对路径</td><td>/testA/testA_B/upload.txt</td></tr>
* <tr><td>/</td><td>uploadFile("/testA/testA_B","upload.txt","up.txt")</td><td>绝对路径</td><td>/testA/testA_B/upload.txt</td></tr>
* </table>
* </p>
* @param pathName SFTP服务器目录
* @param fileName 服务器上保存的文件名
* @param localFile 本地文件
* @return boolean
*/
public boolean uploadFile(String pathName,String fileName,String localFile){ String currentDir = currentDir();
if(!changeDir(pathName)){
return false;
} try {
channel.put(localFile,fileName,ChannelSftp.OVERWRITE);
if(!existFile(fileName)){
logger.debug("upload failed");
return false;
}
logger.debug("upload successful");
return true;
} catch (SftpException e) {
logger.error("upload failed",e);
return false;
} finally {
changeDir(currentDir);
}
} /**
* 下载文件
* <p>
* 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/
* <table border="1">
* <tr><td>当前目录</td><td>方法</td><td>参数:绝对路径/相对路径</td><td>下载后</td></tr>
* <tr><td>/</td><td>downloadFile("testA","down.txt","D:\\downDir")</td><td>相对路径</td><td>D:\\downDir\\down.txt</td></tr>
* <tr><td>/</td><td>downloadFile("testA/testA_B","down.txt","D:\\downDir")</td><td>相对路径</td><td>D:\\downDir\\down.txt</td></tr>
* <tr><td>/</td><td>downloadFile("/testA/testA_B","down.txt","D:\\downDir")</td><td>绝对路径</td><td>D:\\downDir\\down.txt</td></tr>
* </table>
* </p>
* @param remotePath SFTP服务器目录
* @param fileName 服务器上需要下载的文件名
* @param localPath 本地保存路径
* @return boolean
*/
public boolean downloadFile(String remotePath,String fileName,String localPath){ String currentDir = currentDir();
if(!changeDir(remotePath)){
return false;
} try {
String localFilePath = localPath + File.separator + fileName;
channel.get(fileName,localFilePath); File localFile = new File(localFilePath);
if(!localFile.exists()){
logger.debug("download file failed");
return false;
}
logger.debug("download successful");
return true;
} catch (SftpException e) {
logger.error("download file failed",e);
return false;
} finally {
changeDir(currentDir);
}
} /**
* 切换工作目录
* <p>
* 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/
* <table border="1">
* <tr><td>当前目录</td><td>方法</td><td>参数(绝对路径/相对路径)</td><td>切换后的目录</td></tr>
* <tr><td>/</td><td>changeDir("testA")</td><td>相对路径</td><td>/testA/</td></tr>
* <tr><td>/</td><td>changeDir("testA/testA_B")</td><td>相对路径</td><td>/testA/testA_B/</td></tr>
* <tr><td>/</td><td>changeDir("/testA")</td><td>绝对路径</td><td>/testA/</td></tr>
* <tr><td>/testA/testA_B/</td><td>changeDir("/testA")</td><td>绝对路径</td><td>/testA/</td></tr>
* </table>
* </p>
* @param pathName 路径
* @return boolean
*/
public boolean changeDir(String pathName){
if(pathName == null || pathName.trim().equals("")){
logger.debug("invalid pathName");
return false;
} try {
channel.cd(pathName.replaceAll("\\\\", "/"));
logger.debug("directory successfully changed,current dir=" + channel.pwd());
return true;
} catch (SftpException e) {
logger.error("failed to change directory",e);
return false;
}
} /**
* 切换到上一级目录
* <p>
* 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/
* <table border="1">
* <tr><td>当前目录</td><td>方法</td><td>切换后的目录</td></tr>
* <tr><td>/testA/</td><td>changeToParentDir()</td><td>/</td></tr>
* <tr><td>/testA/testA_B/</td><td>changeToParentDir()</td><td>/testA/</td></tr>
* </table>
* </p>
* @return boolean
*/
public boolean changeToParentDir(){
return changeDir("..");
} /**
* 切换到根目录
* @return boolean
*/
public boolean changeToHomeDir(){
String homeDir = null;
try {
homeDir = channel.getHome();
} catch (SftpException e) {
logger.error("can not get home directory",e);
return false;
}
return changeDir(homeDir);
} /**
* 创建目录
* <p>
* 使用示例,SFTP服务器上的目录结构如下:/testA/testA_B/
* <table border="1">
* <tr><td>当前目录</td><td>方法</td><td>参数(绝对路径/相对路径)</td><td>创建成功后的目录</td></tr>
* <tr><td>/testA/testA_B/</td><td>makeDir("testA_B_C")</td><td>相对路径</td><td>/testA/testA_B/testA_B_C/</td></tr>
* <tr><td>/</td><td>makeDir("/testA/testA_B/testA_B_D")</td><td>绝对路径</td><td>/testA/testA_B/testA_B_D/</td></tr>
* </table>
* <br/>
* <b>注意</b>,当<b>中间目录不存在</b>的情况下,不能够使用绝对路径的方式期望创建中间目录及目标目录。
* 例如makeDir("/testNOEXIST1/testNOEXIST2/testNOEXIST3"),这是错误的。
* </p>
* @param dirName 目录
* @return boolean
*/
public boolean makeDir(String dirName){
try {
channel.mkdir(dirName);
logger.debug("directory successfully created,dir=" + dirName);
return true;
} catch (SftpException e) {
logger.error("failed to create directory", e);
return false;
}
} /**
* 删除文件夹
* @param dirName
* @return boolean
*/
@SuppressWarnings("unchecked")
public boolean delDir(String dirName){
if(!changeDir(dirName)){
return false;
} Vector<LsEntry> list = null;
try {
list = channel.ls(channel.pwd());
} catch (SftpException e) {
logger.error("can not list directory",e);
return false;
} for(LsEntry entry : list){
String fileName = entry.getFilename();
if(!fileName.equals(".") && !fileName.equals("..")){
if(entry.getAttrs().isDir()){
delDir(fileName);
} else {
delFile(fileName);
}
}
} if(!changeToParentDir()){
return false;
} try {
channel.rmdir(dirName);
logger.debug("directory " + dirName + " successfully deleted");
return true;
} catch (SftpException e) {
logger.error("failed to delete directory " + dirName,e);
return false;
}
} /**
* 删除文件
* @param fileName 文件名
* @return boolean
*/
public boolean delFile(String fileName){
if(fileName == null || fileName.trim().equals("")){
logger.debug("invalid filename");
return false;
} try {
channel.rm(fileName);
logger.debug("file " + fileName + " successfully deleted");
return true;
} catch (SftpException e) {
logger.error("failed to delete file " + fileName,e);
return false;
}
} /**
* 当前目录下文件及文件夹名称列表
* @return String[]
*/
public String[] ls(){
return list(Filter.ALL);
} /**
* 指定目录下文件及文件夹名称列表
* @return String[]
*/
public String[] ls(String pathName){
String currentDir = currentDir();
if(!changeDir(pathName)){
return new String[0];
};
String[] result = list(Filter.ALL);
if(!changeDir(currentDir)){
return new String[0];
}
return result;
} /**
* 当前目录下文件名称列表
* @return String[]
*/
public String[] lsFiles(){
return list(Filter.FILE);
} /**
* 指定目录下文件名称列表
* @return String[]
*/
public String[] lsFiles(String pathName){
String currentDir = currentDir();
if(!changeDir(pathName)){
return new String[0];
};
String[] result = list(Filter.FILE);
if(!changeDir(currentDir)){
return new String[0];
}
return result;
} /**
* 当前目录下文件夹名称列表
* @return String[]
*/
public String[] lsDirs(){
return list(Filter.DIR);
} /**
* 指定目录下文件夹名称列表
* @return String[]
*/
public String[] lsDirs(String pathName){
String currentDir = currentDir();
if(!changeDir(pathName)){
return new String[0];
};
String[] result = list(Filter.DIR);
if(!changeDir(currentDir)){
return new String[0];
}
return result;
} /**
* 当前目录是否存在文件或文件夹
* @param name 名称
* @return boolean
*/
public boolean exist(String name){
return exist(ls(), name);
} /**
* 指定目录下,是否存在文件或文件夹
* @param path 目录
* @param name 名称
* @return boolean
*/
public boolean exist(String path,String name){
return exist(ls(path),name);
} /**
* 当前目录是否存在文件
* @param name 文件名
* @return boolean
*/
public boolean existFile(String name){
return exist(lsFiles(),name);
} /**
* 指定目录下,是否存在文件
* @param path 目录
* @param name 文件名
* @return boolean
*/
public boolean existFile(String path,String name){
return exist(lsFiles(path), name);
} /**
* 当前目录是否存在文件夹
* @param name 文件夹名称
* @return boolean
*/
public boolean existDir(String name){
return exist(lsDirs(), name);
} /**
* 指定目录下,是否存在文件夹
* @param path 目录
* @param name 文家夹名称
* @return boolean
*/
public boolean existDir(String path,String name){
return exist(lsDirs(path), name);
} /**
* 当前工作目录
* @return String
*/
public String currentDir(){
try {
return channel.pwd();
} catch (SftpException e) {
logger.error("failed to get current dir",e);
return homeDir();
}
} /**
* 登出
*/
public void logout(){
if(channel != null){
channel.quit();
channel.disconnect();
}
if(session != null){
session.disconnect();
}
logger.debug("logout successfully");
} //------private method ------ /** 枚举,用于过滤文件和文件夹 */
private enum Filter {/** 文件及文件夹 */ ALL ,/** 文件 */ FILE ,/** 文件夹 */ DIR }; /**
* 列出当前目录下的文件及文件夹
* @param filter 过滤参数
* @return String[]
*/
@SuppressWarnings("unchecked")
private String[] list(Filter filter){
Vector<LsEntry> list = null;
try {
//ls方法会返回两个特殊的目录,当前目录(.)和父目录(..)
list = channel.ls(channel.pwd());
} catch (SftpException e) {
logger.error("can not list directory",e);
return new String[0];
} List<String> resultList = new ArrayList<String>();
for(LsEntry entry : list){
if(filter(entry, filter)){
resultList.add(entry.getFilename());
}
}
return resultList.toArray(new String[0]);
} /**
* 判断是否是否过滤条件
* @param entry LsEntry
* @param f 过滤参数
* @return boolean
*/
private boolean filter(LsEntry entry,Filter f){
if(f.equals(Filter.ALL)){
return !entry.getFilename().equals(".") && !entry.getFilename().equals("..");
} else if(f.equals(Filter.FILE)){
return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && !entry.getAttrs().isDir();
} else if(f.equals(Filter.DIR)){
return !entry.getFilename().equals(".") && !entry.getFilename().equals("..") && entry.getAttrs().isDir();
}
return false;
} /**
* 根目录
* @return String
*/
private String homeDir(){
try {
return channel.getHome();
} catch (SftpException e) {
return "/";
}
} /**
* 判断字符串是否存在于数组中
* @param strArr 字符串数组
* @param str 字符串
* @return boolean
*/
private boolean exist(String[] strArr,String str){
if(strArr == null || strArr.length == 0){
return false;
}
if(str == null || str.trim().equals("")){
return false;
}
for(String s : strArr){
if(s.equalsIgnoreCase(str)){
return true;
}
}
return false;
} //------private method ------
}

4)测试类

 import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Arrays; public class SftpTest {
public static void main(String[] args) {
// testLogin();
// testMakeDir();
// testDelFile();
// testDelEmptyDir();
// testDir();
// testLs();
// testParamLs();
// testChangeDir();
// testExist();
// testParamExist();
// testUploadFile();
// testUploadFile2();
// testDownload();
} public static void testLogin(){ //OK
Sftp sftp = getSftp(); sftp.login();
sftp.logout();
} public static void testMakeDir(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.makeDir("test2");
sftp.changeDir("test2");
sftp.makeDir("/test2/test2_1");
sftp.logout();
} public static void testDelFile(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.delFile("file1.txt");
sftp.logout();
} public static void testDelEmptyDir(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.delDir("test3");
sftp.logout();
} public static void testDir(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.delDir("test4");
sftp.logout();
} public static void testLs(){ //OK
Sftp sftp = getSftp();
sftp.login();
System.out.println(Arrays.toString(sftp.ls()));
System.out.println(Arrays.toString(sftp.lsFiles()));
System.out.println(Arrays.toString(sftp.lsDirs()));
sftp.logout();
} public static void testParamLs(){ //OK
Sftp sftp = getSftp();
sftp.login();
System.out.println(Arrays.toString(sftp.ls("test1/test4")));
System.out.println(Arrays.toString(sftp.lsFiles("test1/test4")));
System.out.println(Arrays.toString(sftp.lsDirs("test1/test4")));
sftp.logout();
} public static void testChangeDir(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.changeDir("test1");
sftp.changeDir("/test1/test4");
sftp.changeToParentDir();
sftp.changeToHomeDir();
sftp.logout();
} public static void testExist(){ //OK
Sftp sftp = getSftp();
sftp.login();
System.out.println(sftp.exist("2fs.docx"));
System.out.println(sftp.exist("test1"));
System.out.println(sftp.existDir("test2"));
System.out.println(sftp.existDir("2sfs.txt"));
System.out.println(sftp.existFile("2sfs.txt"));
System.out.println(sftp.existFile("test2"));
sftp.logout();
} public static void testParamExist(){ //OK
Sftp sftp = getSftp();
sftp.login();
System.out.println(sftp.exist("test1","test4"));
System.out.println(sftp.exist("test1","test_bak.jpg"));
System.out.println(sftp.existDir("/test1","test3"));
System.out.println(sftp.existDir("/test1","test_bak.jpg"));
System.out.println(sftp.existFile("test1","test_bak.jpg"));
System.out.println(sftp.existFile("test1","test2"));
sftp.logout();
} public static void testUploadFile(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.uploadFile("/test1/test3", "test_bak2.jpg", "D:\\test.jpg");
try {
sftp.uploadFile("/test1/test2", "test_bak3.jpg", new FileInputStream("D:\\test.jpg"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
sftp.logout();
} public static void testUploadFile2(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.uploadFile("test1/test3", "test_bak2.jpg", "D:\\test.jpg");
try {
sftp.uploadFile("test1/test2", "test_bak3.jpg", new FileInputStream("D:\\test.jpg"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
sftp.logout();
} public static void testDownload(){ //OK
Sftp sftp = getSftp();
sftp.login();
sftp.downloadFile("test1", "test_bak.jpg", "D:\\testdown");
sftp.downloadFile("/", "2fs.docx", "D:\\testdown");
sftp.logout();
} private static Sftp getSftp(){ String host = "192.168.10.252";
int port = 22;
int timeout = 60000;
String username = "dongliyang";
String password = "dongliyang"; Sftp sftp = new Sftp(host, port, timeout, username, password); return sftp;
}
}

基于JSch的Sftp工具类的更多相关文章

  1. SFTP工具类

    1.SFTP搭建方法: 地址: http://www.jb51.net/article/101405.htm https://blog.csdn.net/helloloser/article/deta ...

  2. SFTP工具类 操作服务器

    package com.leadbank.oprPlatform.util;import com.jcraft.jsch.*;import com.jcraft.jsch.ChannelSftp.Ls ...

  3. iOS开发——基于corelocation位置定位——工具类

    (代码工具类已写好,空闲时间整理成文档,待更新……)

  4. 基于SqlClient开发SQLServer工具类 伸手党的福音

    注意:代码直接Copy调用即可,SQLServer工具类跟我上一个Oracle工具类有所不同,区别在于调用存储过程中时参数的使用,无需输入对应的存储游标名称 特点:根据用户传入的参数类型来识别存储中对 ...

  5. FTP&plus;SFTP工具类封装-springmore让开发更简单

    github地址:https://github.com/tangyanbo/springmore FTPUtil 该工具基于org.apache.commons.net.ftp.FTPClient进行 ...

  6. jsch连接Linux工具类

    import com.alibaba.fastjson.JSONObject;import com.jcraft.jsch.*;import org.slf4j.Logger;import org.s ...

  7. java SFTP工具类

    需要导入jsch-0.1.52.jar import java.io.File; import java.io.FileInputStream; import java.io.FileOutputSt ...

  8. Java 基于log4j的日志工具类

    对log4j日志类进行了简单封装,使用该封装类的优势在于以下两点: 1.不必在每个类中去创建对象,直接类名 + 方法即可 2.可以很方便的打印出堆栈信息 package com.tradeplatfo ...

  9. 基于durid的JDBCUtils工具类

    1.JDBCUtils类 package com.alphajuns.utils; import com.alibaba.druid.pool.DruidDataSourceFactory; impo ...

随机推荐

  1. 关于MapReduce中自定义Combine类(一)

    MRJobConfig      public static fina COMBINE_CLASS_ATTR      属性COMBINE_CLASS_ATTR = "mapreduce.j ...

  2. LUA学习笔记三&&num;183&semi;时间等操作系统库

    1.构造时间 2.时间制定格式输出 3.计时器(闭包)os.difftime (t2, t1) 返回以秒计算的时刻 t1 到 t2 的差值. (这里的时刻是由 os.time 返回的值). 在 POS ...

  3. tomcat作为服务器的配置

    tomcat在启动时,会读取环境变量的信息,需要一个CATALINA_HOME 与JAVA_HOME的信息,CATALINA_HOME即tomcat的主目录,JAVA_HOME即java安装的主目录, ...

  4. 【转】MySQL中varchar最大长度是多少?

    一. varchar存储规则: 4.0版本以下,varchar(20),指的是20字节,如果存放UTF8汉字时,只能存6个(每个汉字3字节) 5.0版本以上,varchar(20),指的是20字符,无 ...

  5. JavaScript 鼠标划过 播放音乐。

    '<EMBED style="FILTER: xray()" src="mp3/'+s+'" width=360 height=30 type=audio ...

  6. Java核心:类加载和JVM内存的分配

    类的加载: 指的是将class文件的二进制数据读入到运行时数据区(JVM在内存中划分的) 中,并在方法区内创建一个class对象. 类加载器: 负责加载编译后的class文件(字节码文件)到JVM(J ...

  7. &quot&semi;浅谈Android&quot&semi;第一篇:Android系统简介

    近来,看了一本书,名字叫做<第一行代码>,是CSDN一名博主写的,一本Android入门级的书,比较适合新手.看了书之后,有感而发,想来进行Android开发已经有一年多了,但欠缺系统化的 ...

  8. 开发网站相关知识html和javascript

    1.html 布局 https://github.com/bramstein/jlayout/ http://welcome.totheinter.net/columnizer-jquery-plug ...

  9. HTML,JS禁止鼠标右键、禁止全选、复制、粘贴的方法

    禁止鼠标右键.禁止全选.复制.粘贴: oncontextmenu事件禁用右键菜单: js代码: document.oncontextmenu = function(){ event.returnVal ...

  10. thinkphp5和thinkphp3&period;2&period;3中URL重写出现No input file specified

    查询后解决办法是打开public目录下的.htaccess文件,把:RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 改为:RewriteRule ^(.*)$ i ...