广告
返回顶部
首页 > 资讯 > 精选 >SpringBoot如何集成SFTP客户端实现文件上传下载
  • 221
分享到

SpringBoot如何集成SFTP客户端实现文件上传下载

2023-07-06 13:07:04 221人浏览 独家记忆
摘要

这篇文章主要介绍“SpringBoot如何集成SFTP客户端实现文件上传下载”,在日常操作中,相信很多人在springBoot如何集成SFTP客户端实现文件上传下载问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答

这篇文章主要介绍“SpringBoot如何集成SFTP客户端实现文件上传下载”,在日常操作中,相信很多人在springBoot如何集成SFTP客户端实现文件上传下载问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringBoot如何集成SFTP客户端实现文件上传下载”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

背景

项目开发中,一般文件存储很少再使用SFTP服务,但是也不排除合作伙伴使用SFTP来存储项目中的文件或者通过SFTP来实现文件数据的交互。

我遇到的项目中,就有银行和保险公司等合作伙伴通过SFTP服务来实现与我们项目的文件数据的交互。

为了能够顺利地完成与友商的SFTP服务的连通,我们需要在自己的项目中实现一套SFTP客户端工具。一般我们会采用jsch来实现SFTP客户端。

依赖

<!--执行远程操作--><dependency>    <groupId>com.jcraft</groupId>    <artifactId>jsch</artifactId>    <version>0.1.55</version></dependency>     <!--链接池--><dependency>    <groupId>org.apache.commons</groupId>    <artifactId>commons-pool2</artifactId>    <version>2.11.1</version></dependency>

首先我们一定要引入jsch依赖,这个是我们实现SFTP客户端的基石;其次我们引入了链接池工具,为了避免每次执行SFTP命令都要重新创建链接,我们使用池化的方式优化了比较消耗资源的创建操作。

创建工具类

为了更好的使用SFTP工具,我们把jsch中关于SFTP的相关功能提炼出来,做了一次简单的封装,做成了我们可以直接使用的工具类。

里面只有两类方法:

创建Session与开启Session;

session创建好后,还不能创建channel,需要开启session后才能创建channel;

创建channel与开启channel;

channel也是一样,创建好的channel需要开启后才能真正地执行命令;

public class JschUtil {    public static Session createSession(String userName, String passWord, String host, int port, String privateKeyFile, String passphrase) throws AwesomeException {    return createSession(new JSch(), userName, password, host, port, privateKeyFile, passphrase);  }    public static Session createSession(JSch jSch, String userName, String password, String host, int port, String privateKeyFile, String passphrase) throws AwesomeException {    try {      if (!StringUtils.isEmpty(privateKeyFile)) {        // 使用密钥验证方式,密钥可以是有口令的密钥,也可以是没有口令的密钥        if (!StringUtils.isEmpty(passphrase)) {          jSch.addIdentity(privateKeyFile, passphrase);        } else {          jSch.addIdentity(privateKeyFile);        }      }      // 获取session      Session session = jSch.getSession(userName, host, port);      if (!StringUtils.isEmpty(password)) {        session.setPassword(password);      }      // 不校验域名      session.setConfig("StrictHosTKEyChecking", "no");      return session;    } catch (Exception e) {      throw new AwesomeException(500, "create session fail");    }  }    public static Session createSession(JSch jSch, String userName, String password, String host, int port) throws AwesomeException {    return createSession(jSch, userName, password, host, port, StringUtils.EMPTY, StringUtils.EMPTY);  }    private Session createSession(JSch jSch, String userName, String host, int port) throws AwesomeException {    return createSession(jSch, userName, StringUtils.EMPTY, host, port, StringUtils.EMPTY, StringUtils.EMPTY);  }    public static Session openSession(JSch jSch, String userName, String password, String host, int port, String privateKeyFile, String passphrase, int timeout) throws AwesomeException {    Session session = createSession(jSch, userName, password, host, port, privateKeyFile, passphrase);    try {      if (timeout >= 0) {        session.connect(timeout);      } else {        session.connect();      }      return session;    } catch (Exception e) {      throw new AwesomeException(500, "session connect fail");    }  }    public static Session openSession(String userName, String password, String host, int port, String privateKeyFile, String passphrase, int timeout) throws AwesomeException {    Session session = createSession(userName, password, host, port, privateKeyFile, passphrase);    try {      if (timeout >= 0) {        session.connect(timeout);      } else {        session.connect();      }      return session;    } catch (Exception e) {      throw new AwesomeException(500, "session connect fail");    }  }    public static Session openSession(JSch jSch, String userName, String password, String host, int port, int timeout) throws AwesomeException {    return openSession(jSch, userName, password, host, port, StringUtils.EMPTY, StringUtils.EMPTY, timeout);  }    public static Session openSession(String userName, String password, String host, int port, int timeout) throws AwesomeException {    return openSession(userName, password, host, port, StringUtils.EMPTY, StringUtils.EMPTY, timeout);  }    public static Session openSession(JSch jSch, String userName, String host, int port, int timeout) throws AwesomeException {    return openSession(jSch, userName, StringUtils.EMPTY, host, port, StringUtils.EMPTY, StringUtils.EMPTY, timeout);  }    public static Session openSession(String userName, String host, int port, int timeout) throws AwesomeException {    return openSession(userName, StringUtils.EMPTY, host, port, StringUtils.EMPTY, StringUtils.EMPTY, timeout);  }    public static Channel createChannel(Session session, ChannelType channelType) throws AwesomeException {    try {      if (!session.isConnected()) {        session.connect();      }      return session.openChannel(channelType.getValue());    } catch (Exception e) {      throw new AwesomeException(500, "open channel fail");    }  }    public static ChannelSftp createSftp(Session session) throws AwesomeException {    return (ChannelSftp) createChannel(session, ChannelType.SFTP);  }    public static Channelshell createShell(Session session) throws AwesomeException {    return (ChannelShell) createChannel(session, ChannelType.SHELL);  }    public static Channel openChannel(Session session, ChannelType channelType, int timeout) throws AwesomeException {    Channel channel = createChannel(session, channelType);    try {      if (timeout >= 0) {        channel.connect(timeout);      } else {        channel.connect();      }      return channel;    } catch (Exception e) {      throw new AwesomeException(500, "connect channel fail");    }  }    public static ChannelSftp openSftpChannel(Session session, int timeout) throws AwesomeException {    return (ChannelSftp) openChannel(session, ChannelType.SFTP, timeout);  }    public static ChannelShell openShellChannel(Session session, int timeout) throws AwesomeException {    return (ChannelShell) openChannel(session, ChannelType.SHELL, timeout);  }  enum ChannelType {    SESSION("session"),    SHELL("shell"),    EXEC("exec"),    X11("x11"),    AGENT_FORWARDING("auth-agent@openssh.com"),    DIRECT_tcpIP("direct-tcpip"),    FORWARDED_TCPIP("forwarded-tcpip"),    SFTP("sftp"),    SUBSYSTEM("subsystem");    private final String value;    ChannelType(String value) {      this.value = value;    }    public String getValue() {      return this.value;    }  }}

SFTP链接池化

我们通过实现BasePooledObjectFactory类来池化通道ChannelSftp。这并不是真正池化的代码,下面的代码只是告知池化管理器如何创建对象和销毁对象。

static class SftpFactory extends BasePooledObjectFactory<ChannelSftp> implements AutoCloseable {    private Session session;    private SftpProperties properties;    // 初始化SftpFactory    // 里面主要是创建目标session,后续可用通过这个session不断地创建ChannelSftp。    SftpFactory(SftpProperties properties) throws AwesomeException {      this.properties = properties;      String username = properties.getUsername();      String password = properties.getPassword();      String host = properties.getHost();      int port = properties.getPort();      String privateKeyFile = properties.getPrivateKeyFile();      String passphrase = properties.getPassphrase();      session = JschUtil.createSession(username, password, host, port, privateKeyFile, passphrase);    }    // 销毁对象,主要是销毁ChannelSftp    @Override    public void destroyObject(PooledObject<ChannelSftp> p) throws Exception {      p.getObject().disconnect();    }    // 创建对象ChannelSftp    @Override    public ChannelSftp create() throws Exception {      int timeout = properties.getTimeout();      return JschUtil.openSftpChannel(this.session, timeout);    }    // 包装创建出来的对象    @Override    public PooledObject<ChannelSftp> wrap(ChannelSftp channelSftp) {      return new DefaultPooledObject<>(channelSftp);    }    // 验证对象是否可用    @Override    public boolean validateObject(PooledObject<ChannelSftp> p) {      return p.getObject().isConnected();    }    // 销毁资源,关闭session    @Override    public void close() throws Exception {      if (Objects.nonNull(session)) {        if (session.isConnected()) {          session.disconnect();        }        session = null;      }    }  }

为了实现真正的池化操作,我们还需要以下代码:

我们需要在SftpClient对象中创建一个GenericObjectPool对象池,这个才是真正的池子,它负责创建和存储所有的对象。

我们还需要提供资源销毁的功能,也就是实现AutoCloseable,在服务停止时,需要把相关的资源销毁。

public class SftpClient implements AutoCloseable {  private SftpFactory sftpFactory;  GenericObjectPool<ChannelSftp> objectPool;  // 构造方法1  public SftpClient(SftpProperties properties, GenericObjectPoolConfig<ChannelSftp> poolConfig) throws AwesomeException {    this.sftpFactory = new SftpFactory(properties);    objectPool = new GenericObjectPool<>(this.sftpFactory, poolConfig);  }  // 构造方法2  public SftpClient(SftpProperties properties) throws AwesomeException {    this.sftpFactory = new SftpFactory(properties);    SftpProperties.PoolConfig config = properties.getPool();    // 默认池化配置    if (Objects.isNull(config)) {      objectPool = new GenericObjectPool<>(this.sftpFactory);    } else {      // 自定义池化配置      GenericObjectPoolConfig<ChannelSftp> poolConfig = new GenericObjectPoolConfig<>();      poolConfig.setMaxIdle(config.getMaxIdle());      poolConfig.setMaxTotal(config.getMaxTotal());      poolConfig.setMinIdle(config.getMinIdle());      poolConfig.setTestOnBorrow(config.isTestOnBorrow());      poolConfig.setTestOnCreate(config.isTestOnCreate());      poolConfig.setTestOnReturn(config.isTestOnReturn());      poolConfig.setTestWhileIdle(config.isTestWhileIdle());      poolConfig.setBlockWhenExhausted(config.isBlockWhenExhausted());      poolConfig.setMaxWait(Duration.ofMillis(config.getMaxWaitMillis()));      poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(config.getTimeBetweenEvictionRunsMillis()));      objectPool = new GenericObjectPool<>(this.sftpFactory, poolConfig);    }  }    // 销毁资源    @Override  public void close() throws Exception {    // 销毁链接池    if (Objects.nonNull(this.objectPool)) {      if (!this.objectPool.isClosed()) {        this.objectPool.close();      }    }    this.objectPool = null;    // 销毁sftpFactory    if (Objects.nonNull(this.sftpFactory)) {      this.sftpFactory.close();    }  }}

SFTP链接池的使用

我们已经对链接池进行了初始化,下面我们就可以从链接池中获取我们需要的ChannelSftp来实现文件的上传下载了。

下面实现了多种文件上传和下载的方式:

直接把本地文件上传到SFTP服务器的指定路径;

把InputStream输入流提交到SFTP服务器指定路径中;

可以针对以上两种上传方式进行进度的监测;

把SFTP服务器中的指定文件下载到本地机器上;

把SFTP服务器˙中的文件写入指定的输出流;

针对以上两种下载方式,监测下载进度;

    public boolean uploadFile(String srcFilePath, String targetDir, String targetFileName) throws AwesomeException {    return uploadFile(srcFilePath, targetDir, targetFileName, null);  }    public boolean uploadFile(String srcFilePath, String targetDir, String targetFileName, SftpProgreSSMonitor monitor) throws AwesomeException {    ChannelSftp channelSftp = null;    try {      // 从链接池获取对象      channelSftp = this.objectPool.borrowObject();      // 如果不存在目标文件夹      if (!exist(channelSftp, targetDir)) {        mkdirs(channelSftp, targetDir);      }      channelSftp.cd(targetDir);      // 上传文件      if (Objects.nonNull(monitor)) {        channelSftp.put(srcFilePath, targetFileName, monitor);      } else {        channelSftp.put(srcFilePath, targetFileName);      }      return true;    } catch (Exception e) {      throw new AwesomeException(500, "upload file fail");    } finally {      if (Objects.nonNull(channelSftp)) {        // 返还对象给链接池        this.objectPool.returnObject(channelSftp);      }    }  }    public boolean uploadFile(InputStream in, String targetDir, String targetFileName) throws AwesomeException {    return uploadFile(in, targetDir, targetFileName, null);  }    public boolean uploadFile(InputStream in, String targetDir, String targetFileName, SftpProgressMonitor monitor) throws AwesomeException {    ChannelSftp channelSftp = null;    try {      channelSftp = this.objectPool.borrowObject();      // 如果不存在目标文件夹      if (!exist(channelSftp, targetDir)) {        mkdirs(channelSftp, targetDir);      }      channelSftp.cd(targetDir);      if (Objects.nonNull(monitor)) {        channelSftp.put(in, targetFileName, monitor);      } else {        channelSftp.put(in, targetFileName);      }      return true;    } catch (Exception e) {      throw new AwesomeException(500, "upload file fail");    } finally {      if (Objects.nonNull(channelSftp)) {        this.objectPool.returnObject(channelSftp);      }    }  }    public boolean downloadFile(String remoteFile, String targetFilePath) throws AwesomeException {    return downloadFile(remoteFile, targetFilePath, null);  }    public boolean downloadFile(String remoteFile, String targetFilePath, SftpProgressMonitor monitor) throws AwesomeException {    ChannelSftp channelSftp = null;    try {      channelSftp = this.objectPool.borrowObject();      // 如果不存在目标文件夹      if (!exist(channelSftp, remoteFile)) {        // 不用下载了        return false;      }      File targetFile = new File(targetFilePath);      try (FileOutputStream outputStream = new FileOutputStream(targetFile)) {        if (Objects.nonNull(monitor)) {          channelSftp.get(remoteFile, outputStream, monitor);        } else {          channelSftp.get(remoteFile, outputStream);        }      }      return true;    } catch (Exception e) {      throw new AwesomeException(500, "upload file fail");    } finally {      if (Objects.nonNull(channelSftp)) {        this.objectPool.returnObject(channelSftp);      }    }  }    public boolean downloadFile(String remoteFile, OutputStream outputStream) throws AwesomeException {    return downloadFile(remoteFile, outputStream, null);  }    public boolean downloadFile(String remoteFile, OutputStream outputStream, SftpProgressMonitor monitor) throws AwesomeException {    ChannelSftp channelSftp = null;    try {      channelSftp = this.objectPool.borrowObject();      // 如果不存在目标文件夹      if (!exist(channelSftp, remoteFile)) {        // 不用下载了        return false;      }      if (Objects.nonNull(monitor)) {        channelSftp.get(remoteFile, outputStream, monitor);      } else {        channelSftp.get(remoteFile, outputStream);      }      return true;    } catch (Exception e) {      throw new AwesomeException(500, "upload file fail");    } finally {      if (Objects.nonNull(channelSftp)) {        this.objectPool.returnObject(channelSftp);      }    }  }    protected boolean mkdirs(ChannelSftp channelSftp, String dir) {    try {      String pwd = channelSftp.pwd();      if (StringUtils.contains(pwd, dir)) {        return true;      }      String relativePath = StringUtils.substringAfter(dir, pwd);      String[] dirs = StringUtils.splitByWholeSeparatorPreserveAllTokens(relativePath, "/");      for (String path : dirs) {        if (StringUtils.isBlank(path)) {          continue;        }        try {          channelSftp.cd(path);        } catch (SftpException e) {          channelSftp.mkdir(path);          channelSftp.cd(path);        }      }      return true;    } catch (Exception e) {      return false;    }  }    protected boolean exist(ChannelSftp channelSftp, String dir) {    try {      channelSftp.lstat(dir);      return true;    } catch (Exception e) {      return false;    }  }

集成到SpringBoot中

我们可以通过java config的方式,把我们已经实现好的SftpClient类实例化到Spring ioc容器中来管理,以便让开发人员在整个项目中通过@Autowired的方式就可以直接使用。

配置
import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;@Data@Configuration@ConfigurationProperties(prefix = "sftp.config")public class SftpProperties {  // 用户名  private String username;  // 密码  private String password;  // 主机名  private String host;  // 端口  private int port;  // 密钥  private String privateKeyFile;  // 口令  private String passphrase;  // 通道链接超时时间  private int timeout;  // 链接池配置  private PoolConfig pool;  @Data  public static class PoolConfig {    //最大空闲实例数,空闲超过此值将会被销毁淘汰    private int maxIdle;    // 最小空闲实例数,对象池将至少保留2个空闲对象    private int minIdle;    //最大对象数量,包含借出去的和空闲的    private int maxTotal;    //对象池满了,是否阻塞获取(false则借不到直接抛异常)    private boolean blockWhenExhausted;    // BlockWhenExhausted为true时生效,对象池满了阻塞获取超时,不设置则阻塞获取不超时,也可在borrowObject方法传递第二个参数指定本次的超时时间    private long maxWaitMillis;    // 创建对象后是否验证对象,调用objectFactory#validateObject    private boolean testOnCreate;    // 借用对象后是否验证对象 validateObject    private boolean testOnBorrow;    // 归还对象后是否验证对象 validateObject    private boolean testOnReturn;    // 定时检查期间是否验证对象 validateObject    private boolean testWhileIdle;    //定时检查淘汰多余的对象, 启用单独的线程处理    private long timeBetweenEvictionRunsMillis;    //jmx监控,和springboot自带的jmx冲突,可以选择关闭此配置或关闭springboot的jmx配置    private boolean jmxEnabled;  }}
java Bean注入
import com.example.awesomespring.exception.AwesomeException;import com.example.awesomespring.sftp.SftpClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class SftpConfig {  @Autowired  private SftpProperties properties;  // 创建SftpClient对象  @Bean(destroyMethod = "close")  @ConditionalOnProperty(prefix = "sftp.config")  public SftpClient sftpClient() throws AwesomeException {    return new SftpClient(properties);  }}

通过以上代码,我们就可以在项目的任何地方直接使用SFTP客户端来上传和下载文件了。

到此,关于“SpringBoot如何集成SFTP客户端实现文件上传下载”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: SpringBoot如何集成SFTP客户端实现文件上传下载

本文链接: https://www.lsjlt.com/news/358444.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot如何集成SFTP客户端实现文件上传下载
    这篇文章主要介绍“SpringBoot如何集成SFTP客户端实现文件上传下载”,在日常操作中,相信很多人在SpringBoot如何集成SFTP客户端实现文件上传下载问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答...
    99+
    2023-07-06
  • QtQFtp客户端实现上传下载文件
    目录1.简介2.用到的主要类2.1QNetworkReply2.2QNetworkRequest3.示例3.1本地搭建一个FTP服务器。3.2示例1.简介 实现FTP客户端有几种方式...
    99+
    2022-11-13
  • SpringBoot如何实现上传和下载文件
    这篇文章主要介绍SpringBoot如何实现上传和下载文件,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!技术概述我们的项目是实现一个论坛。在论坛上发布博客时应该要可以上传文件,用户阅读博客是应该要可以下载文件。于是我...
    99+
    2023-06-20
  • SpringBoot集成FastDFS依赖如何实现文件上传
    这篇文章主要介绍SpringBoot集成FastDFS依赖如何实现文件上传,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、引入依赖简单说一下这个依赖部分,目前大部分都是采用的如下依赖:<!-- ht...
    99+
    2023-06-15
  • SpringBoot如何实现文件上传与下载功能
    今天小编给大家分享一下SpringBoot如何实现文件上传与下载功能的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Sprin...
    99+
    2023-07-02
  • Java如何使用Sftp和Ftp实现对文件的上传和下载
    这篇文章将为大家详细讲解有关Java如何使用Sftp和Ftp实现对文件的上传和下载,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。第一步,导入maven依赖<!-- FTP依赖包 ...
    99+
    2023-06-14
  • HTML5如何实现文件上传下载
    这篇文章主要介绍了HTML5如何实现文件上传下载,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言HTML5 中提供的文件API在前端中有着...
    99+
    2022-10-19
  • Django 如何实现文件上传下载
    目录1. 前言 2. 实战一下 2-1  进入虚拟环境,创建一个项目及 App2-2  创建模板目录并配置 settings.py2-3  创...
    99+
    2022-11-12
  • Django如何实现文件上传下载
    小编给大家分享一下Django如何实现文件上传下载,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!1. 前言文件上传、下载作为基础功能,在 Web 项目中非常普遍,...
    99+
    2023-06-14
  • SpringMVC如何实现文件上传下载
    本篇内容主要讲解“SpringMVC如何实现文件上传下载”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringMVC如何实现文件上传下载”吧!一、通用配置pom.xml  ...
    99+
    2023-06-22
  • php如何实现文件的上传和下载
    这篇文章将为大家详细讲解有关php如何实现文件的上传和下载,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。php有什么用php是一个嵌套的缩写名称,是英文超级文本预处理语言,它的语法混合了C、Java、Pe...
    99+
    2023-06-14
  • SpringBoot+微信小程序如何实现文件上传与下载功能
    这篇文章主要介绍SpringBoot+微信小程序如何实现文件上传与下载功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、文件上传1.1 后端部分1.1 引入Apache Commons FIleUpload组件依...
    99+
    2023-06-29
  • SpringMVC如何使用ResponseEntity实现文件上传下载
    本篇内容主要讲解“SpringMVC如何使用ResponseEntity实现文件上传下载”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringMVC如何使用ResponseEntity实现文...
    99+
    2023-06-30
  • Retrofit+Rxjava如何实现文件上传和下载功能
    这篇文章主要介绍Retrofit+Rxjava如何实现文件上传和下载功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Retrofit简介:在Android API4.4之后,Google官方使用了square公司推...
    99+
    2023-05-30
    retrofit rxjava
  • Servlet如何实现文件的上传与下载功能
    这篇文章给大家分享的是有关Servlet如何实现文件的上传与下载功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。实现条件:需要一个form标签,method为post请求2、form的encType属性值为mu...
    99+
    2023-06-14
  • Blob对象如何实现文件上传下载功能
    本篇内容介绍了“Blob对象如何实现文件上传下载功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是Blod?Blob 对象表示一个不可...
    99+
    2023-07-04
  • 如何在PHP中实现大文件上传和下载
    随着互联网技术的发展,越来越多的应用场景需要实现大文件上传和下载功能。在PHP的应用中,如何实现高效、稳定、安全的大文件上传和下载?下面我们将介绍一些实用的技巧和方法。一、大文件上传分段上传上传大文件时,一次性上传整个文件容易出现网络超时、...
    99+
    2023-05-21
    PHP 大文件上传 大文件下载
  • vue与django如何实现文件上传下载功能
    本篇内容主要讲解“vue与django如何实现文件上传下载功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue与django如何实现文件上传下载功能”吧!文件上传功能上传后端部分(一)Mod...
    99+
    2023-07-05
  • JavaWeb是如何实现文件上传和下载功能
    这篇文章将为大家详细讲解有关JavaWeb是如何实现文件上传和下载功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. 文件传输原理及介绍2. JavaWeb文件上传2.1我们用一个新的方...
    99+
    2023-06-22
  • 详解JavaWeb如何实现文件上传和下载功能
    目录1.文件传输原理及介绍2.JavaWeb文件上传2.1我们用一个新的方式创建项目2.2导包2.3实用类介绍2.4pom.xml导入需要的依赖2.5index.jsp2.6info...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作