Android中FTP上传、下载的功能实现(含进度)

Android中使用的FTP上传、下载,含有进度。

代码部分主要分为三个文件:MainActivity,FTP,ProgressInputStream

1. MainActivity

package com.ftp; 

import java.io.File;
import java.io.IOException;
import java.util.LinkedList; 

import com.ftp.FTP.DeleteFileProgressListener;
import com.ftp.FTP.DownLoadProgressListener;
import com.ftp.FTP.UploadProgressListener; 

import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast; 

public class MainActivity extends Activity { 

  private static final String TAG = "MainActivity"; 

  public static final String FTP_CONNECT_SUCCESSS = "ftp连接成功";
  public static final String FTP_CONNECT_FAIL = "ftp连接失败";
  public static final String FTP_DISCONNECT_SUCCESS = "ftp断开连接";
  public static final String FTP_FILE_NOTEXISTS = "ftp上文件不存在"; 

  public static final String FTP_UPLOAD_SUCCESS = "ftp文件上传成功";
  public static final String FTP_UPLOAD_FAIL = "ftp文件上传失败";
  public static final String FTP_UPLOAD_LOADING = "ftp文件正在上传"; 

  public static final String FTP_DOWN_LOADING = "ftp文件正在下载";
  public static final String FTP_DOWN_SUCCESS = "ftp文件下载成功";
  public static final String FTP_DOWN_FAIL = "ftp文件下载失败"; 

  public static final String FTP_DELETEFILE_SUCCESS = "ftp文件删除成功";
  public static final String FTP_DELETEFILE_FAIL = "ftp文件删除失败"; 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main); 

    initView();
  } 

  private void initView() { 

    //上传功能
    //new FTP().uploadMultiFile为多文件上传
    //new FTP().uploadSingleFile为单文件上传
    Button buttonUpload = (Button) findViewById(R.id.button_upload);
    buttonUpload.setOnClickListener(new OnClickListener() {
      @Override
      public void onClick(View v) { 

          new Thread(new Runnable() {
            @Override
            public void run() { 

              // 上传
              File file = new File("/mnt/sdcard/ftpTest.docx");
              try { 

                //单文件上传
                new FTP().uploadSingleFile(file, "/fff",new UploadProgressListener(){ 

                  @Override
                  public void onUploadProgress(String currentStep,long uploadSize,File file) {
                    // TODO Auto-generated method stub
                    Log.d(TAG, currentStep);
                    if(currentStep.equals(MainActivity.FTP_UPLOAD_SUCCESS)){
                      Log.d(TAG, "-----shanchuan--successful");
                    } else if(currentStep.equals(MainActivity.FTP_UPLOAD_LOADING)){
                      long fize = file.length();
                      float num = (float)uploadSize / (float)fize;
                      int result = (int)(num * 100);
                      Log.d(TAG, "-----shangchuan---"+result + "%");
                    }
                  }
                });
              } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
              } 

            }
          }).start(); 

      }
    }); 

    //下载功能
    Button buttonDown = (Button)findViewById(R.id.button_down);
    buttonDown.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) { 

        new Thread(new Runnable() {
          @Override
          public void run() { 

            // 下载
            try { 

              //单文件下载
              new FTP().downloadSingleFile("/fff/ftpTest.docx","/mnt/sdcard/download/","ftpTest.docx",new DownLoadProgressListener(){ 

                @Override
                public void onDownLoadProgress(String currentStep, long downProcess, File file) {
                  Log.d(TAG, currentStep);
                  if(currentStep.equals(MainActivity.FTP_DOWN_SUCCESS)){
                    Log.d(TAG, "-----xiazai--successful");
                  } else if(currentStep.equals(MainActivity.FTP_DOWN_LOADING)){
                    Log.d(TAG, "-----xiazai---"+downProcess + "%");
                  }
                } 

              });              

            } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            } 

          }
        }).start(); 

      }
    }); 

    //删除功能
    Button buttonDelete = (Button)findViewById(R.id.button_delete);
    buttonDelete.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) { 

        new Thread(new Runnable() {
          @Override
          public void run() { 

            // 删除
            try { 

              new FTP().deleteSingleFile("/fff/ftpTest.docx",new DeleteFileProgressListener(){ 

                @Override
                public void onDeleteProgress(String currentStep) {
                  Log.d(TAG, currentStep);
                  if(currentStep.equals(MainActivity.FTP_DELETEFILE_SUCCESS)){
                    Log.d(TAG, "-----shanchu--success");
                  } else if(currentStep.equals(MainActivity.FTP_DELETEFILE_FAIL)){
                    Log.d(TAG, "-----shanchu--fail");
                  }
                } 

              });              

            } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            } 

          }
        }).start(); 

      }
    }); 

  }
}

2. FTP

package com.ftp; 

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.LinkedList;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply; 

public class FTP {
  /**
   * 服务器名.
   */
  private String hostName; 

  /**
   * 端口号
   */
  private int serverPort; 

  /**
   * 用户名.
   */
  private String userName; 

  /**
   * 密码.
   */
  private String password; 

  /**
   * FTP连接.
   */
  private FTPClient ftpClient; 

  public FTP() {
    this.hostName = "192.168.1.101";
    this.serverPort = 21;
    this.userName = "admin";
    this.password = "1234";
    this.ftpClient = new FTPClient();
  } 

  // -------------------------------------------------------文件上传方法------------------------------------------------ 

  /**
   * 上传单个文件.
   *
   * @param localFile
   *      本地文件
   * @param remotePath
   *      FTP目录
   * @param listener
   *      监听器
   * @throws IOException
   */
  public void uploadSingleFile(File singleFile, String remotePath,
      UploadProgressListener listener) throws IOException { 

    // 上传之前初始化
    this.uploadBeforeOperate(remotePath, listener); 

    boolean flag;
    flag = uploadingSingle(singleFile, listener);
    if (flag) {
      listener.onUploadProgress(MainActivity.FTP_UPLOAD_SUCCESS, 0,
          singleFile);
    } else {
      listener.onUploadProgress(MainActivity.FTP_UPLOAD_FAIL, 0,
          singleFile);
    } 

    // 上传完成之后关闭连接
    this.uploadAfterOperate(listener);
  } 

  /**
   * 上传多个文件.
   *
   * @param localFile
   *      本地文件
   * @param remotePath
   *      FTP目录
   * @param listener
   *      监听器
   * @throws IOException
   */
  public void uploadMultiFile(LinkedList<File> fileList, String remotePath,
      UploadProgressListener listener) throws IOException { 

    // 上传之前初始化
    this.uploadBeforeOperate(remotePath, listener); 

    boolean flag; 

    for (File singleFile : fileList) {
      flag = uploadingSingle(singleFile, listener);
      if (flag) {
        listener.onUploadProgress(MainActivity.FTP_UPLOAD_SUCCESS, 0,
            singleFile);
      } else {
        listener.onUploadProgress(MainActivity.FTP_UPLOAD_FAIL, 0,
            singleFile);
      }
    } 

    // 上传完成之后关闭连接
    this.uploadAfterOperate(listener);
  } 

  /**
   * 上传单个文件.
   *
   * @param localFile
   *      本地文件
   * @return true上传成功, false上传失败
   * @throws IOException
   */
  private boolean uploadingSingle(File localFile,
      UploadProgressListener listener) throws IOException {
    boolean flag = true;
    // 不带进度的方式
    // // 创建输入流
    // InputStream inputStream = new FileInputStream(localFile);
    // // 上传单个文件
    // flag = ftpClient.storeFile(localFile.getName(), inputStream);
    // // 关闭文件流
    // inputStream.close(); 

    // 带有进度的方式
    BufferedInputStream buffIn = new BufferedInputStream(
        new FileInputStream(localFile));
    ProgressInputStream progressInput = new ProgressInputStream(buffIn,
        listener, localFile);
    flag = ftpClient.storeFile(localFile.getName(), progressInput);
    buffIn.close(); 

    return flag;
  } 

  /**
   * 上传文件之前初始化相关参数
   *
   * @param remotePath
   *      FTP目录
   * @param listener
   *      监听器
   * @throws IOException
   */
  private void uploadBeforeOperate(String remotePath,
      UploadProgressListener listener) throws IOException { 

    // 打开FTP服务
    try {
      this.openConnect();
      listener.onUploadProgress(MainActivity.FTP_CONNECT_SUCCESSS, 0,
          null);
    } catch (IOException e1) {
      e1.printStackTrace();
      listener.onUploadProgress(MainActivity.FTP_CONNECT_FAIL, 0, null);
      return;
    } 

    // 设置模式
    ftpClient.setFileTransferMode(org.apache.commons.net.ftp.FTP.STREAM_TRANSFER_MODE);
    // FTP下创建文件夹
    ftpClient.makeDirectory(remotePath);
    // 改变FTP目录
    ftpClient.changeWorkingDirectory(remotePath);
    // 上传单个文件 

  } 

  /**
   * 上传完成之后关闭连接
   *
   * @param listener
   * @throws IOException
   */
  private void uploadAfterOperate(UploadProgressListener listener)
      throws IOException {
    this.closeConnect();
    listener.onUploadProgress(MainActivity.FTP_DISCONNECT_SUCCESS, 0, null);
  } 

  // -------------------------------------------------------文件下载方法------------------------------------------------ 

  /**
   * 下载单个文件,可实现断点下载.
   *
   * @param serverPath
   *      Ftp目录及文件路径
   * @param localPath
   *      本地目录
   * @param fileName
   *      下载之后的文件名称
   * @param listener
   *      监听器
   * @throws IOException
   */
  public void downloadSingleFile(String serverPath, String localPath, String fileName, DownLoadProgressListener listener)
      throws Exception { 

    // 打开FTP服务
    try {
      this.openConnect();
      listener.onDownLoadProgress(MainActivity.FTP_CONNECT_SUCCESSS, 0, null);
    } catch (IOException e1) {
      e1.printStackTrace();
      listener.onDownLoadProgress(MainActivity.FTP_CONNECT_FAIL, 0, null);
      return;
    } 

    // 先判断服务器文件是否存在
    FTPFile[] files = ftpClient.listFiles(serverPath);
    if (files.length == 0) {
      listener.onDownLoadProgress(MainActivity.FTP_FILE_NOTEXISTS, 0, null);
      return;
    } 

    //创建本地文件夹
    File mkFile = new File(localPath);
    if (!mkFile.exists()) {
      mkFile.mkdirs();
    } 

    localPath = localPath + fileName;
    // 接着判断下载的文件是否能断点下载
    long serverSize = files[0].getSize(); // 获取远程文件的长度
    File localFile = new File(localPath);
    long localSize = 0;
    if (localFile.exists()) {
      localSize = localFile.length(); // 如果本地文件存在,获取本地文件的长度
      if (localSize >= serverSize) {
        File file = new File(localPath);
        file.delete();
      }
    } 

    // 进度
    long step = serverSize / 100;
    long process = 0;
    long currentSize = 0;
    // 开始准备下载文件
    OutputStream out = new FileOutputStream(localFile, true);
    ftpClient.setRestartOffset(localSize);
    InputStream input = ftpClient.retrieveFileStream(serverPath);
    byte[] b = new byte[1024];
    int length = 0;
    while ((length = input.read(b)) != -1) {
      out.write(b, 0, length);
      currentSize = currentSize + length;
      if (currentSize / step != process) {
        process = currentSize / step;
        if (process % 5 == 0) { //每隔%5的进度返回一次
          listener.onDownLoadProgress(MainActivity.FTP_DOWN_LOADING, process, null);
        }
      }
    }
    out.flush();
    out.close();
    input.close(); 

    // 此方法是来确保流处理完毕,如果没有此方法,可能会造成现程序死掉
    if (ftpClient.completePendingCommand()) {
      listener.onDownLoadProgress(MainActivity.FTP_DOWN_SUCCESS, 0, new File(localPath));
    } else {
      listener.onDownLoadProgress(MainActivity.FTP_DOWN_FAIL, 0, null);
    } 

    // 下载完成之后关闭连接
    this.closeConnect();
    listener.onDownLoadProgress(MainActivity.FTP_DISCONNECT_SUCCESS, 0, null); 

    return;
  } 

  // -------------------------------------------------------文件删除方法------------------------------------------------ 

  /**
   * 删除Ftp下的文件.
   *
   * @param serverPath
   *      Ftp目录及文件路径
   * @param listener
   *      监听器
   * @throws IOException
   */
  public void deleteSingleFile(String serverPath, DeleteFileProgressListener listener)
      throws Exception { 

    // 打开FTP服务
    try {
      this.openConnect();
      listener.onDeleteProgress(MainActivity.FTP_CONNECT_SUCCESSS);
    } catch (IOException e1) {
      e1.printStackTrace();
      listener.onDeleteProgress(MainActivity.FTP_CONNECT_FAIL);
      return;
    } 

    // 先判断服务器文件是否存在
    FTPFile[] files = ftpClient.listFiles(serverPath);
    if (files.length == 0) {
      listener.onDeleteProgress(MainActivity.FTP_FILE_NOTEXISTS);
      return;
    } 

    //进行删除操作
    boolean flag = true;
    flag = ftpClient.deleteFile(serverPath);
    if (flag) {
      listener.onDeleteProgress(MainActivity.FTP_DELETEFILE_SUCCESS);
    } else {
      listener.onDeleteProgress(MainActivity.FTP_DELETEFILE_FAIL);
    } 

    // 删除完成之后关闭连接
    this.closeConnect();
    listener.onDeleteProgress(MainActivity.FTP_DISCONNECT_SUCCESS); 

    return;
  } 

  // -------------------------------------------------------打开关闭连接------------------------------------------------ 

  /**
   * 打开FTP服务.
   *
   * @throws IOException
   */
  public void openConnect() throws IOException {
    // 中文转码
    ftpClient.setControlEncoding("UTF-8");
    int reply; // 服务器响应值
    // 连接至服务器
    ftpClient.connect(hostName, serverPort);
    // 获取响应值
    reply = ftpClient.getReplyCode();
    if (!FTPReply.isPositiveCompletion(reply)) {
      // 断开连接
      ftpClient.disconnect();
      throw new IOException("connect fail: " + reply);
    }
    // 登录到服务器
    ftpClient.login(userName, password);
    // 获取响应值
    reply = ftpClient.getReplyCode();
    if (!FTPReply.isPositiveCompletion(reply)) {
      // 断开连接
      ftpClient.disconnect();
      throw new IOException("connect fail: " + reply);
    } else {
      // 获取登录信息
      FTPClientConfig config = new FTPClientConfig(ftpClient
          .getSystemType().split(" ")[0]);
      config.setServerLanguageCode("zh");
      ftpClient.configure(config);
      // 使用被动模式设为默认
      ftpClient.enterLocalPassiveMode();
      // 二进制文件支持
      ftpClient
          .setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
    }
  } 

  /**
   * 关闭FTP服务.
   *
   * @throws IOException
   */
  public void closeConnect() throws IOException {
    if (ftpClient != null) {
      // 退出FTP
      ftpClient.logout();
      // 断开连接
      ftpClient.disconnect();
    }
  } 

  // ---------------------------------------------------上传、下载、删除监听--------------------------------------------- 

  /*
   * 上传进度监听
   */
  public interface UploadProgressListener {
    public void onUploadProgress(String currentStep, long uploadSize, File file);
  } 

  /*
   * 下载进度监听
   */
  public interface DownLoadProgressListener {
    public void onDownLoadProgress(String currentStep, long downProcess, File file);
  } 

  /*
   * 文件删除监听
   */
  public interface DeleteFileProgressListener {
    public void onDeleteProgress(String currentStep);
  } 

}

3. ProgressInputStream

package com.ftp; 

import java.io.File;
import java.io.IOException;
import java.io.InputStream; 

import com.ftp.FTP.UploadProgressListener; 

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log; 

public class ProgressInputStream extends InputStream { 

  private static final int TEN_KILOBYTES = 1024 * 10; //每上传10K返回一次 

  private InputStream inputStream; 

  private long progress;
  private long lastUpdate; 

  private boolean closed; 

  private UploadProgressListener listener;
  private File localFile; 

  public ProgressInputStream(InputStream inputStream,UploadProgressListener listener,File localFile) {
    this.inputStream = inputStream;
    this.progress = 0;
    this.lastUpdate = 0;
    this.listener = listener;
    this.localFile = localFile; 

    this.closed = false;
  } 

  @Override
  public int read() throws IOException {
    int count = inputStream.read();
    return incrementCounterAndUpdateDisplay(count);
  } 

  @Override
  public int read(byte[] b, int off, int len) throws IOException {
    int count = inputStream.read(b, off, len);
    return incrementCounterAndUpdateDisplay(count);
  } 

  @Override
  public void close() throws IOException {
    super.close();
    if (closed)
      throw new IOException("already closed");
    closed = true;
  } 

  private int incrementCounterAndUpdateDisplay(int count) {
    if (count > 0)
      progress += count;
    lastUpdate = maybeUpdateDisplay(progress, lastUpdate);
    return count;
  } 

  private long maybeUpdateDisplay(long progress, long lastUpdate) {
    if (progress - lastUpdate > TEN_KILOBYTES) {
      lastUpdate = progress;
      this.listener.onUploadProgress(MainActivity.FTP_UPLOAD_LOADING, progress, this.localFile);
    }
    return lastUpdate;
  } 

}

原文链接:http://blog.csdn.net/tianyitianyi1/article/details/38637999

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android FTP 多线程断点续传下载\上传的实例

    最近在给我的开源下载框架Aria增加FTP断点续传下载和上传功能,在此过程中,爬了FTP的不少坑,终于将功能实现了,在此把一些核心功能点记录下载. FTP下载原理 FTP单线程断点续传 FTP和传统的HTTP协议有所不同,由于FTP没有所谓的头文件,因此我们不能像HTTP那样通过设置header向服务器指定下载区间. 但是FTP协议提供了一个更好用的命令REST用于从指定位置恢复任务,同时FTP协议也提供了一个命令SIZE用于获取下载的文件大小,有了这两个命令,FTP断点续传也就没有什么问题.

  • Android关于FTP文件上传和下载功能详解

    本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下 此篇博客为整理文章,供大家学习. 1.首先下载commons-net  jar包,可以百度下载. FTP的文件上传和下载的工具类: package ryancheng.example.progressbar; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.Outpu

  • shell脚本实现ftp上传下载文件功能

    前段时间工作中需要将经过我司平台某些信息核验数据提取后上传到客户的FTP服务器上,以便于他们进行相关的信息比对核验.由于包含这些信息的主机只有4台,采取的策略是将生成的4个文件汇集到一个主机上,然后在这台主机上将文件上传的目标ftp服务器. 1,建立主机A到其他三台主机之间的信任关系,以便于远程拷贝文件 #生成主机A的本地认证秘钥,可以选择生成rsa或者dsa类型的秘钥,这里选取rsa [root@A ~]#ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa >/d

  • Java FTP上传下载删除功能实例代码

    在没给大家上完整代码之前先给大家说下注意点: FTP上传下载,容易出现乱码,记得转换 package com.yinhai.team.action; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; impo

  • Android中FTP上传、下载的功能实现(含进度)

    Android中使用的FTP上传.下载,含有进度. 代码部分主要分为三个文件:MainActivity,FTP,ProgressInputStream 1. MainActivity package com.ftp; import java.io.File; import java.io.IOException; import java.util.LinkedList; import com.ftp.FTP.DeleteFileProgressListener; import com.ftp.F

  • Java语言实现简单FTP软件 FTP上传下载管理模块实现(11)

    本文为大家分享了FTP上传下载管理模块的实现方法,供大家参考,具体内容如下 1.上传本地文件或文件夹到远程FTP服务器端的功能. 当用户在本地文件列表中选择想要上传的文件后,点击上传按钮,将本机上指定的文件上传到FTP服务器当前展现的目录,下图为上传子模块流程图 选择好要上传的文件或文件夹,点击"上传"按钮,会触发com.oyp.ftp.panel.local.UploadAction类的actionPerformed(ActionEvent e)方法,其主要代码如下 /** * 上传

  • Java实现ftp上传下载、删除文件及在ftp服务器上传文件夹的方法

    一个JAVA 实现FTP功能的代码,包括了服务器的设置模块,并包括有上传文件至FTP的通用方法.下载文件的通用方法以及删除文件.在ftp服务器上传文件夹.检测文件夹是否存在等,里面的有些代码对编写JAVA文件上传或许有参考价值,Java FTP主文件代码: package ftpDemo; import java.io.DataOutputStream; import java.io.InputStream; import java.io.OutputStream; import sun.net

  • Spring FTP上传下载工具类遇到问题小结

    前言 最近在项目中需要和ftp服务器进行交互,在网上找了一下关于ftp上传下载的工具类,大致有两种. 第一种是单例模式的类. 第二种是另外定义一个Service,直接通过Service来实现ftp的上传下载. 这两种感觉都有利弊. 第一种实现了代码复用,但是配置信息全需要写在类中,维护比较复杂. 第二种如果是spring框架,可以通过propertis文件,动态的注入配置信息,但是又不能代码复用. 所以我打算自己实现一个工具类,来把上面的两种优点进行整合.顺便把一些上传过程中一些常见的问题也给解

  • python实现的简单FTP上传下载文件实例

    本文实例讲述了python实现的简单FTP上传下载文件的方法.分享给大家供大家参考.具体如下: python本身自带一个FTP模块,可以实现上传下载的函数功能. #!/usr/bin/env python # -*- coding: utf-8 -*- from ftplib import FTP def ftp_up(filename = "20120904.rar"): ftp=FTP() ftp.set_debuglevel(2) #打开调试级别2,显示详细信息;0为关闭调试信息

  • Java语言实现简单FTP软件 FTP上传下载队列窗口实现(7)

    本文为大家介绍了FTP上传下载队列窗口的实现方法,供大家参考,具体内容如下 1.首先看一下队列窗口的界面 2.看一下上传队列窗口的界面 3.看一下下载队列窗口的界面 package com.oyp.ftp.panel.queue; import static java.awt.BorderLayout.CENTER; import static java.awt.BorderLayout.EAST; import static javax.swing.ListSelectionModel.SIN

  • springboot 中文件上传下载实例代码

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. Spring Boot特点 1. 创建独立的Spring应用程序 2. 嵌入的Tomcat,无需部署WAR文件 3. 简化Maven配置 4. 自动配置Spr

  • springboot操作阿里云OSS实现文件上传,下载,删除功能

    参考资料:Java操作阿里云OSS操作官方文档 学会看文档,并实际运用也是一种习惯和技能 下面就来简单入门一下,用当下比较热门的Springboot 去操作阿里云OSS文件存储. 1.需求 (没踩过下面的坑的小伙伴可以直接跳过这一章节) 问题简述 首先,我在之前自己做一些开源小项目案例中遇到一些文件上传下载的问题,比如在本机文件上传和下载都可以正常使用,通过将文件上传到Springboot项目的根目录下,按日期分文件夹,文件访问也很方便,可以直接返回文件相对路径地址,并直接可以访问. 问题 然而

随机推荐