Soluciones a problemas relacionados con JAVA FTPClient (velocidad lenta, caracteres chinos ilegibles y pérdida de contenido)

La solución a la velocidad de caracol de la carga de archivos de FTPClient

La velocidad de carga del archivo FTPClient LAN de Apache Commons debería ser muy rápida, pero en el desarrollo real, se encontró que la velocidad de carga de un archivo es pequeña, porque se llama a la siguiente API:

ftpClient.storeFile (nombre de archivo, flujo de entrada)

El motivo es que el tamaño del búfer predeterminado es 1024, que es 1K, por supuesto que es lento, simplemente modifique la siguiente configuración predeterminada antes de llamar a la API de carga, como cambiar el búfer a 10M, API:

ftpClient.setBufferSize(1024 * 1024 * 10)

Para configurar antes de llamar a storeFile()

Después de cargar un archivo a través de FTPclient, el contenido del archivo se distorsiona (el archivo está dañado)

Al subir archivos con FTPClient de Apache me encontré con un problema, es decir no hay problema al subir archivos txt, pero al subir archivos zip se destruyen los archivos, después de comprobar el motivo resultó ser así:

Porque RFC959 estipula que el modo de transmisión predeterminado debe ser ASCII, y la implementación de org.apache.commons.net.ftp.FTPClient también cumple con este estándar. Entonces, org.apache.commons.net.ftp.FTPClient transmite en formato ASCII de forma predeterminada. Si transmite un archivo binario BINARIO (como zip), el archivo cargado se destruirá, pero la transferencia de archivos ASCII (como txt) no es un problema. .

Entonces, si está transfiriendo archivos binarios BINARIOS, debe configurar el tipo de archivo después de establecer una conexión e iniciar sesión. El ejemplo de código es el siguiente:

ftpclient.connect(host);
ftpclient.login(usuario, contraseña);
ftpclient.setFileType(FTPClient.BINARY_FILE_TYPE);

Preste atención al pedido, el tipo de configuración debe colocarse después de iniciar sesión; de lo contrario, no tendrá efecto

Después de cargar un archivo a través de FTPclient, el nombre del archivo en chino es ilegible

La solución simple es:
convertir el directorio chino o el nombre del archivo a caracteres codificados iso-8859-1. Código de referencia:

String name="nombre de directorio o nombre de archivo"; name=nuevo
String(name.getBytes("GBK"),"iso-8859-1");

Después de que muchas personas cambiaron a la operación anterior, descubrieron que los caracteres chinos ya no estaban distorsionados después de cargarlos, y pensaron que el problema estaba resuelto.
Algunas personas también resolvieron el problema de la siguiente manera:

ftpClient.setControlEncoding(“GBK”);
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode(“zh”);

Este método no considera el formato de codificación del servidor ftp. El servidor FTP (servidor Windows 2003) creado localmente admite la codificación GBK, por lo que la solución anterior está bien, pero el servidor FTP (serv-u) admite el formato UTF-8, por lo que el método de codificación en el lado del cliente es GBK en este momento, y La configuración en el servidor ftp configurado ya está codificada en utf-8, por lo que definitivamente habrá caracteres ilegibles.
Puede elegir qué codificación usar verificando si el servidor es compatible con UTF8

if (FTPReply.isPositiveCompletion(ftpClient.sendCommand( "OPTS UTF8", "ON"))) { // Habilite el servidor para admitir UTF-8, si el servidor admite la codificación UTF-8; de lo contrario, use la codificación local (GBK) .LOCAL_CHARSET = "UTF-8";}

el código

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** 通过FTP上传文件 @Author lvhaibao @Date 2018/2/11 21:43 */
public class FTPTools {
    
    
  private static final Logger log = LoggerFactory.getLogger(FTPTools.class);

  /* 解决文件夹和文件名乱码*/
  /** 本地字符编码 */
  private static String LOCAL_CHARSET = "GBK";

  // FTP协议里面,规定文件名编码为iso-8859-1
  private static String SERVER_CHARSET = "ISO-8859-1";

  // 设置私有不能实例化
  private FTPTools() {
    
    }

  /**
   * 上传
   *
   * @param hostname
   * @param port
   * @param username
   * @param password
   * @param workingPath 服务器的工作目录
   * @param inputStream 文件的输入流
   * @param saveName 要保存的文件名
   * @return
   */
  public static boolean upload(
      String hostname,
      int port,
      String username,
      String password,
      String workingPath,
      InputStream inputStream,
      String saveName) {
    
    
    boolean flag = false;
    FTPClient ftpClient = new FTPClient();
    // 1 测试连接
    if (connect(ftpClient, hostname, port, username, password)) {
    
    
      try {
    
    
        // TODO 调试时查看该目录下文件
        FTPFile[] ftpFiles = ftpClient.listFiles(workingPath);
        for (FTPFile ftpFile : ftpFiles) {
    
    
          System.out.println(ftpFile.getName());
        }
        // 2 检查工作目录是否存在
        if (!ftpClient.changeWorkingDirectory(workingPath)) {
    
    
          // 如果目录不存在则创建目录
          // 因为ftp只支持一级级创建,固拆分后一级级创建
          String[] dirs = workingPath.split("/");
          String tempPath = "";
          for (String dir : dirs) {
    
    
            if (null == dir || "".equals(dir)) {
    
    
              continue;
            }
            tempPath += "/" + dir;
            if (!ftpClient.changeWorkingDirectory(tempPath)) {
    
    
              // ftp创建文件夹是否成功
              boolean b = ftpClient.makeDirectory(tempPath);
              if (!b) {
    
    
                return flag;
              } else {
    
    
                ftpClient.changeWorkingDirectory(tempPath);
              }
            }
          }
        }
        // 3 检查是否上传成功
        flag = storeFile(ftpClient, saveName, inputStream);
      } catch (IOException e) {
    
    
        log.error("工作目录不存在", e);
      } finally {
    
    
        disconnect(ftpClient);
      }
    }
    return flag;
  }

  /**
   * 断开连接
   *
   * @param ftpClient
   */
  public static void disconnect(FTPClient ftpClient) {
    
    
    if (ftpClient.isConnected()) {
    
    
      try {
    
    
        ftpClient.disconnect();
        log.info("已关闭连接");
      } catch (IOException e) {
    
    
        log.error("没有关闭连接", e);
      }
    }
  }

  /**
   * 测试是否能连接
   *
   * @param ftpClient
   * @param hostname ip或域名地址
   * @param port 端口
   * @param username 用户名
   * @param password 密码
   * @return 返回真则能连接
   */
  public static boolean connect(
      FTPClient ftpClient, String hostname, int port, String username, String password) {
    
    
    boolean flag = false;
    try {
    
    
      ftpClient.enterLocalPassiveMode();
      ftpClient.connect(hostname, port);
      // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
      if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
    
    
        LOCAL_CHARSET = "UTF-8";
      }
      ftpClient.setControlEncoding(LOCAL_CHARSET);
      if (ftpClient.login(username, password)) {
    
    
        // 设置文件类型必须放到登录后才生效,否则上传上去的文件内容依然乱码
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        log.info("连接ftp成功");
        flag = true;
      } else {
    
    
        disconnect(ftpClient);
        throw new RuntimeException("登录FTP失败,报告未生成!可能FTP用户名或密码错误!");
      }
    } catch (IOException e) {
    
    
      log.error("连接失败,可能ip或端口错误", e);
    }
    return flag;
  }

  /**
   * 上传文件
   *
   * @param ftpClient
   * @param saveName 全路径。如/home/public/a.txt
   * @param fileInputStream 输入的文件流
   * @return
   */
  public static boolean storeFile(
      FTPClient ftpClient, String saveName, InputStream fileInputStream) {
    
    
    boolean flag = false;
    try {
    
    
      ftpClient.setFileTransferMode(FTPClient.BINARY_FILE_TYPE);
      // 将缓存区变大,提升上传效果
      ftpClient.setBufferSize(1024 * 1024 * 10);
      flag = ftpClient.storeFile(saveName, fileInputStream);
      log.info("上传成功");
    } catch (IOException e) {
    
    
      log.error("上传失败", e);
    } finally {
    
    
      disconnect(ftpClient);
    }
    return flag;
  }

  public static void main(String[] args) throws FileNotFoundException {
    
    
    String hostname = "192.168.0.134";
    int port = 21;
    String username = "ceshi";
    String password = "test";
    String workingPath = "/test";
    String str = "C:\\Users\\T480S\\Desktop\\DF-5B-test-DF-5B-001-test.pdf";
    InputStream fileInputStream = new FileInputStream(new File(str));
        String saveName = "TS文档.docx";
    try {
    
    
      // 上传文件时,文件名称需要做编码转换
      saveName = new String(saveName.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
    } catch (UnsupportedEncodingException e) {
    
    
      e.printStackTrace();
    }

    System.out.println(
        FTPTools.upload(
            hostname, port, username, password, workingPath, fileInputStream, saveName));
  }
}

Supongo que te gusta

Origin blog.csdn.net/qq_43961619/article/details/111317580
Recomendado
Clasificación