Java程序批量拷贝服务器文件到阿里云OSS

青旬

        最近遇到一个问题就是公司的阿里云服务器上的文件快把盘给撑爆了,而且监总要求要拷贝2020年前的文件。但是文件特别多,而且搜索文件这方面做了优化(文件夹特别多),所以得编写一个全自动文件拷贝程序。

        公司的文件夹结构形式是这样的

/data0/fastdfs_storage_data/data
    ├── 00
    │   ├── 00
    │   │   ├── (各种图片文件)
    │   ├── 01
    │   │   ├── (各种图片文件)
    │   ├── 02

    │   │   ├── (各种图片文件)
    │   ├── ........(省略)
    ├── 01

    │   ├── ........(省略)
    ├── 02

    │   ├── ........(省略)
    ├── ......(省略)

    ├── FF

例如 /data0/fastdfs_storage_data/data/00/00/文件名1(第一个文件)

         /data0/fastdfs_storage_data/data/00/0A/文件名2

         /data0/fastdfs_storage_data/data/1B/FF/文件名3

         /data0/fastdfs_storage_data/data/FF/FF/文件名4(最后一个文件)

 服务器文件拷贝到 阿里云 oss

      代码在这:

        先创建一个OssProperties

  1. public class OssProperties {
  2. // 阿里云oss地址
  3. private String ossaddress = "";
  4. // 两个密钥信息
  5. private String accessKeyId = "";
  6. private String accessKeySecret = "";
  7. // 桶名称
  8. private String bucketName = "";
  9. // 服务器文件存储地址
  10. private String filePath = "";
  11. public String getOssaddress() {
  12. return ossaddress;
  13. }
  14. public void setOssaddress(String ossaddress) {
  15. this.ossaddress = ossaddress;
  16. }
  17. public String getBucketName() {
  18. return bucketName;
  19. }
  20. public void setBucketName(String bucketName) {
  21. this.bucketName = bucketName;
  22. }
  23. public String getFilePath() {
  24. return filePath;
  25. }
  26. public void setFilePath(String filePath) {
  27. this.filePath = filePath;
  28. }
  29. public void setAccessKeyId(String accessKeyId) {
  30. this.accessKeyId = accessKeyId;
  31. }
  32. public void setAccessKeySecret(String accessKeySecret) {
  33. this.accessKeySecret = accessKeySecret;
  34. }
  35. public String getAccessKeyId() {
  36. return accessKeyId;
  37. }
  38. public String getAccessKeySecret() {
  39. return accessKeySecret;
  40. }
  41. }

然后开始编写文件 上传代码

  1. import com.aliyun.oss.OSSClient;
  2. import com.aliyun.oss.model.ObjectMetadata;
  3. import com.aliyun.oss.model.PutObjectResult;
  4. import entity.OssProperties;
  5. import java.io.File;
  6. import java.io.FileInputStream;
  7. import java.io.InputStream;
  8. import java.nio.file.Files;
  9. import java.nio.file.Paths;
  10. import java.nio.file.attribute.BasicFileAttributes;
  11. import java.nio.file.attribute.FileTime;
  12. import java.text.SimpleDateFormat;
  13. import java.util.Date;
  14. public class test {
  15. static OssProperties ossProperties = new OssProperties();
  16. final static String IMGADDRESS = ""; // OSS文件目录
  17. public static void main(String[] args) throws Exception {
  18. System.out.println("程序启动");
  19. long startTime = System.currentTimeMillis();
  20. // 设置运行时间为 5 * 3600 * 1000 毫秒(5个小时)
  21. long stopTime = 5 * 3600 * 1000;
  22. System.out.println("开始拷贝...");
  23. OSSClient client = new OSSClient(ossProperties.getOssaddress(), ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());
  24. for(int i = 0; i < 256; i++) {
  25. for (int j = 0; j < 256; j++) {
  26. // 超过指定时间之后直接停止程序
  27. long endTime = System.currentTimeMillis();
  28. if (endTime - startTime > stopTime) {
  29. System.out.println("拷贝到时,已停止...");
  30. // 停止之后计时时间为 19 * 3600 * 1000 毫秒
  31. Thread.sleep(19 * 3600 * 1000);
  32. startTime = System.currentTimeMillis();
  33. }
  34. String a = encodeHEX(i);
  35. String b = encodeHEX(j);
  36. System.out.println("在/" + a + '/' + b + "目录下拷贝中...");
  37. ossProperties.setFilePath(IMGADDRESS + a + '/' + b + '/');
  38. String flilePathName = "/data0/fastdfs_storage_data/data/" + a + '/' + b + "/"; // 将文件存储到OSS目录的地址
  39. File file = new File(flilePathName);
  40. File[] files = file.listFiles();
  41. if (files == null) {
  42. System.out.println(a + '/' + b + "目录为空");
  43. continue;
  44. }
  45. for (File f : files) {
  46. BasicFileAttributes attrs = Files.readAttributes(Paths.get(f.getAbsolutePath()), BasicFileAttributes.class);
  47. // 从基本属性类中获取文件创建时间
  48. FileTime fileTime = attrs.creationTime();
  49. // 将文件创建时间转成毫秒
  50. long millis = fileTime.toMillis();
  51. SimpleDateFormat dateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
  52. Date date = new Date();
  53. date.setTime(millis);
  54. // 毫秒转成时间字符串
  55. String time = dateFormat.format(date);
  56. // 这里根据时间来判断将20年之前的文件拷贝到OSS上
  57. if (time.compareTo("2020-01-01 00:00:00") <= 0) {
  58. uploadObjectOSS(client, f);
  59. System.out.println(time + " " + f.getName());
  60. // 拷贝完成之后删除文件
  61. f.delete();
  62. }
  63. }
  64. }
  65. }
  66. System.out.println("拷贝完成!");
  67. client.shutdown();
  68. }
  69. //10进制数字转16进制字符串
  70. public static String encodeHEX(Integer numb){
  71. String hex= Integer.toHexString(numb);
  72. hex = hex.toUpperCase();
  73. if (hex.length() < 2) {
  74. hex = "0" + hex;
  75. }
  76. return hex;
  77. }
  78. // 向阿里云的OSS存储中存储文件
  79. public static String uploadObjectOSS(OSSClient client, File file) {
  80. String resultStr = null;
  81. try {
  82. InputStream is = new FileInputStream(file);
  83. String fileName = file.getName();
  84. Long fileSize = file.length();
  85. //创建上传Object的Metadata
  86. ObjectMetadata metadata = new ObjectMetadata();
  87. metadata.setContentLength(is.available());
  88. metadata.setCacheControl("no-cache");
  89. metadata.setHeader("Pragma", "no-cache");
  90. metadata.setContentEncoding("utf-8");
  91. metadata.setContentType(getContentType(fileName));
  92. metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte.");
  93. //上传文件
  94. PutObjectResult putResult = client.putObject(ossProperties.getBucketName(), ossProperties.getFilePath() + fileName, is, metadata);
  95. //解析结果
  96. resultStr = putResult.getETag();
  97. is.close();
  98. } catch (Exception e) {
  99. e.printStackTrace();
  100. }
  101. return resultStr;
  102. }
  103. // 通过文件名判断并获取OSS服务文件上传时文件的contentType
  104. public static final String getContentType(String fileName){
  105. String fileExtension = fileName.substring(fileName.lastIndexOf(".")+1);
  106. if("bmp".equalsIgnoreCase(fileExtension)) return "image/bmp";
  107. if("gif".equalsIgnoreCase(fileExtension)) return "image/gif";
  108. if("jpeg".equalsIgnoreCase(fileExtension) || "jpg".equalsIgnoreCase(fileExtension) ) return "image/jpeg";
  109. if("png".equalsIgnoreCase(fileExtension)) return "image/png";
  110. if("html".equalsIgnoreCase(fileExtension)) return "text/html";
  111. if("txt".equalsIgnoreCase(fileExtension)) return "text/plain";
  112. if("vsd".equalsIgnoreCase(fileExtension)) return "application/vnd.visio";
  113. if("ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) return "application/vnd.ms-powerpoint";
  114. if("doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) return "application/msword";
  115. if("xml".equalsIgnoreCase(fileExtension)) return "text/xml";
  116. return "text/html";
  117. }
  118. }

        将程序打包成jar包,放到linux服务器上运行nohup java -jar "你的jar包名字".jar &就可以运行了,日志会输出到nohup.out文件上。

阿里云oss文件拷贝到服务器

        拷贝功能实现了,如果后期出现需要将文件拷贝回来的情况还是要重新写一个程序的,但是网上大部分文章都没有写如何拷贝阿里云oss上的文件夹,所以这里我也写好应对此情况的程序了。

        OssProperties 上面写了,这里我就直接放代码

  1. import com.aliyun.oss.OSSClient;
  2. import com.aliyun.oss.model.GetObjectRequest;
  3. import com.aliyun.oss.model.ListObjectsRequest;
  4. import com.aliyun.oss.model.OSSObjectSummary;
  5. import com.aliyun.oss.model.ObjectListing;
  6. import entity.OssProperties;
  7. import java.io.File;
  8. import java.util.ArrayList;
  9. public class test {
  10. static OssProperties ossProperties = new OssProperties();
  11. public static void main(String[] args) throws Exception {
  12. System.out.println("开始运行...");
  13. OSSClient ossClient = new OSSClient(ossProperties.getOssaddress(), ossProperties.getAccessKeyId(), ossProperties.getAccessKeySecret());
  14. // 构造ListObjectsRequest请求
  15. ListObjectsRequest listObjectsRequest = new ListObjectsRequest(ossProperties.getBucketName());
  16. //Delimiter 设置为 “/” 时,罗列该文件夹下的文件
  17. listObjectsRequest.setDelimiter("/");
  18. for(int i = 0; i < 256; i++) {
  19. for (int j = 0; j < 256; j++) {
  20. String a = encodeHEX(i);
  21. String b = encodeHEX(j);
  22. //Prefix 设为某个文件夹名,罗列以此 Prefix 开头的文件
  23. listObjectsRequest.setPrefix("FastDFS_bak/data/" + a + '/' + b + '/'); // 这里写需要拷贝的文件夹名称
  24. ObjectListing listing = ossClient.listObjects(listObjectsRequest);
  25. ArrayList<String> list = new ArrayList<>();
  26. // 遍历所有Object:目录下的文件
  27. for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
  28. String key = objectSummary.getKey();
  29. System.out.println(key);
  30. // OSS存储文件的路径
  31. String basePath = key;
  32. // 下载到本地的目录,自己随意存放
  33. String localPath = ""; // oss文件拷贝到服务器的存放路径
  34. // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
  35. ossClient.getObject(new GetObjectRequest(ossProperties.getBucketName(), basePath), new File(localPath + key.substring(16)));
  36. }
  37. }
  38. }
  39. System.out.println("运行完毕...");
  40. ossClient.shutdown();
  41. }
  42. //10进制数字转16进制字符串
  43. public static String encodeHEX(Integer numb){
  44. String hex= Integer.toHexString(numb);
  45. hex = hex.toUpperCase();
  46. if (hex.length() < 2) {
  47. hex = "0" + hex;
  48. }
  49. return hex;
  50. }
  51. }

        还是同样的部署操作,将程序打包成jar包,放到 linux 服务器上运行nohup java -jar "你的jar包名字".jar &就可以运行了,日志会输出到nohup.out文件上。