diff --git a/pom.xml b/pom.xml
index eb9ce29..96f6cd2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -210,7 +210,12 @@
xinge
1.2.4.22
-
+
+
+ com.qcloud
+ cos_api-bundle
+ 5.6.238
+
com.github.houbb
diff --git a/src/main/java/com/onekeycall/videotablet/config/CommonConfig.java b/src/main/java/com/onekeycall/videotablet/config/CommonConfig.java
index ce2f750..98931aa 100644
--- a/src/main/java/com/onekeycall/videotablet/config/CommonConfig.java
+++ b/src/main/java/com/onekeycall/videotablet/config/CommonConfig.java
@@ -1,11 +1,8 @@
package com.onekeycall.videotablet.config;
-import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class CommonConfig {
-
+ public static final String ROOT_URL = "https://api.onekeycall.com";
}
\ No newline at end of file
diff --git a/src/main/java/com/onekeycall/videotablet/config/FilePath.java b/src/main/java/com/onekeycall/videotablet/config/FilePath.java
index e313631..6b5b8fc 100644
--- a/src/main/java/com/onekeycall/videotablet/config/FilePath.java
+++ b/src/main/java/com/onekeycall/videotablet/config/FilePath.java
@@ -2,7 +2,6 @@ package com.onekeycall.videotablet.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
import java.io.File;
@@ -19,6 +18,7 @@ public class FilePath {
public static final String TABLET_PATH = "tablet";
public static final String AVATAR_PATH = "avatar";
public static final String APK_ICON_PATH = "apkIcon";
+ public static final String SCREENSHOT_PATH = "screenshot";
public static String getRootPath() {
String osName = System.getProperty("os.name");
@@ -39,4 +39,8 @@ public class FilePath {
public static String getApkIconPath() {
return getRootPath() + File.separator + TABLET_PATH + File.separator + APK_ICON_PATH + File.separator;
}
+
+ public static String getScreenshotPath() {
+ return getRootPath() + File.separator + TABLET_PATH + File.separator + SCREENSHOT_PATH + File.separator;
+ }
}
diff --git a/src/main/java/com/onekeycall/videotablet/config/PushIdConfig.java b/src/main/java/com/onekeycall/videotablet/config/PushIdConfig.java
index c6ef19e..aef581a 100644
--- a/src/main/java/com/onekeycall/videotablet/config/PushIdConfig.java
+++ b/src/main/java/com/onekeycall/videotablet/config/PushIdConfig.java
@@ -18,4 +18,7 @@ public class PushIdConfig {
public static final String CONTACT_VIDEO = "16";
public static final String CONTACT_DELETE = "17";
+ public static final String SCREEN_SNAPSHOT = "18";
+
+
}
diff --git a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java
index ac91a09..ba85894 100644
--- a/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java
+++ b/src/main/java/com/onekeycall/videotablet/config/SecurityConfig.java
@@ -34,7 +34,6 @@ public class SecurityConfig {
.authorizeHttpRequests(auth -> auth
.requestMatchers("/ws/**").permitAll()
.requestMatchers("/api/ws/**", "/topic/**").permitAll()
- .requestMatchers("/uploadFile/**").permitAll()
.requestMatchers("/public/**").permitAll()
// .requestMatchers("/sn/**").permitAll()
// .requestMatchers("/user/**").permitAll()
@@ -42,6 +41,8 @@ public class SecurityConfig {
.requestMatchers("/admin/**").hasRole("ADMIN")
// .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.requestMatchers("/contact/**").permitAll()
+ .requestMatchers("/uploadFile/**").permitAll()
+ .requestMatchers("/data/**").permitAll()
.anyRequest().authenticated()
);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); // 添加JWT过滤器
diff --git a/src/main/java/com/onekeycall/videotablet/config/WebConfig.java b/src/main/java/com/onekeycall/videotablet/config/WebConfig.java
index 5915077..744d987 100644
--- a/src/main/java/com/onekeycall/videotablet/config/WebConfig.java
+++ b/src/main/java/com/onekeycall/videotablet/config/WebConfig.java
@@ -22,6 +22,9 @@ public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/uploadFile/**").addResourceLocations("file:uploadFile/");
+ registry.addResourceHandler("/uploadFile/**")
+ .addResourceLocations("file:uploadFile/");
+ registry.addResourceHandler("/data/uploads/**")
+ .addResourceLocations("file:/data/uploads/");
}
}
diff --git a/src/main/java/com/onekeycall/videotablet/controller/sn/DevicesController.java b/src/main/java/com/onekeycall/videotablet/controller/sn/DevicesController.java
index be0dc87..4962dfc 100644
--- a/src/main/java/com/onekeycall/videotablet/controller/sn/DevicesController.java
+++ b/src/main/java/com/onekeycall/videotablet/controller/sn/DevicesController.java
@@ -1,15 +1,9 @@
package com.onekeycall.videotablet.controller.sn;
import com.onekeycall.videotablet.config.FilePath;
-import com.onekeycall.videotablet.entity.ApkIconFileInfo;
-import com.onekeycall.videotablet.entity.Contact;
-import com.onekeycall.videotablet.entity.DeviceInfo;
-import com.onekeycall.videotablet.entity.DeviceLocation;
+import com.onekeycall.videotablet.entity.*;
import com.onekeycall.videotablet.result.Result;
-import com.onekeycall.videotablet.service.ApkIconService;
-import com.onekeycall.videotablet.service.ContactService;
-import com.onekeycall.videotablet.service.DeviceLocationService;
-import com.onekeycall.videotablet.service.DeviceSnService;
+import com.onekeycall.videotablet.service.*;
import com.onekeycall.videotablet.utils.HashUtils;
import com.onekeycall.videotablet.utils.JwtUtil;
import com.onekeycall.videotablet.utils.TextUtils;
@@ -38,6 +32,8 @@ public class DevicesController {
private ContactService contactService;
@Autowired
private ApkIconService apkIconService;
+ @Autowired
+ private ScreenshotService screenshotService;
Logger logger = LoggerFactory.getLogger(DevicesController.class);
@@ -157,4 +153,36 @@ public class DevicesController {
return Result.ok();
}
+
+ @PostMapping("/upload_screenshot")
+ public Result uploadScreenshot(
+ @RequestPart(value = "file") MultipartFile file,
+ @RequestParam(value = "sn") String sn
+ ) throws Exception {
+ String screenshotPath = FilePath.getScreenshotPath();
+ logger.info("uploadScreenshot, screenshotPath: {}", screenshotPath);
+ File fileDir = new File(screenshotPath);
+ if (!fileDir.exists()) {
+ fileDir.mkdirs();
+ }
+
+ String originName = file.getOriginalFilename();
+ String fileExtension = FilenameUtils.getExtension(originName);
+ String hash = HashUtils.calculateMultipartFileMd5(file);
+ String fileName = sn + "_" + System.currentTimeMillis() + "_" + hash + "." + fileExtension;
+ File destFile = new File(fileDir, fileName);
+ try {
+ file.transferTo(destFile);
+ ScreenshotInfo screenshotInfo =new ScreenshotInfo();
+ screenshotInfo.setSn(sn);
+ screenshotInfo.setFile_name(fileName);
+ screenshotInfo.setUpload_time(new Date(System.currentTimeMillis()).getTime());
+ screenshotService.save(screenshotInfo);
+ } catch (Exception e) {
+ logger.error("uploadScreenshot error", e.getMessage());
+ return Result.error().message("upload screenshot error");
+ }
+
+ return Result.ok();
+ }
}
diff --git a/src/main/java/com/onekeycall/videotablet/controller/user/UserController.java b/src/main/java/com/onekeycall/videotablet/controller/user/UserController.java
index 3ac2c24..c72d092 100644
--- a/src/main/java/com/onekeycall/videotablet/controller/user/UserController.java
+++ b/src/main/java/com/onekeycall/videotablet/controller/user/UserController.java
@@ -46,6 +46,8 @@ public class UserController {
private DeviceApkInfoService deviceApkInfoService;
@Autowired
private ApkIconService apkIconService;
+ @Autowired
+ private ScreenshotService screenshotService;
Logger logger = LoggerFactory.getLogger(LoginController.class);
@@ -262,7 +264,7 @@ public class UserController {
) throws ExecutionException, InterruptedException {
Map params = new HashMap<>();
params.put("package_name", packageName);
- switch (action){
+ switch (action) {
case "open":
DevicePushUtils.aliyunAsyncPush(PushIdConfig.OPEN_APP, sn, GsonUtils.toJSONString(params));
break;
@@ -280,4 +282,44 @@ public class UserController {
}
return Result.ok().message("success");
}
+
+
+ @PostMapping("/screen_snapshot")
+ public Result screenSnapshot(@RequestParam String sn) throws ExecutionException, InterruptedException {
+ Map params = new HashMap<>();
+ params.put("sn", sn);
+ params.put("timestamp", System.currentTimeMillis());
+ DevicePushUtils.aliyunAsyncPush(PushIdConfig.SCREEN_SNAPSHOT, sn, GsonUtils.toJSONString(params));
+ return Result.ok().message("success");
+ }
+
+ @GetMapping("/get_snapshot")
+ public Result getScreenSnapshot(@RequestParam String sn) {
+ List screenSnapshot = screenshotService.findBySn(sn);
+ if (screenSnapshot == null) {
+ return Result.notFound().message("Screen snapshot not found");
+ }
+ return Result.ok().data(screenSnapshot);
+ }
+
+ @PostMapping("/delete_all_snapshot")
+ public Result deleteAllScreenSnapshot(@RequestParam String sn) {
+ screenshotService.deleteAllBySn(sn);
+ return Result.ok().message("success");
+ }
+
+ @PostMapping("/delete_snapshot")
+ public Result deleteScreenSnapshot(@RequestParam String sn, @RequestParam Long id) {
+ if (screenshotService.existsBySnAndId(sn, id)) {
+ boolean deleteSuccess = screenshotService.deleteBySnAndId(sn, id);
+ if (deleteSuccess) {
+ logger.info("deleteScreenSnapshot success, sn: {}, id: {}", sn, id);
+ } else {
+ logger.info("deleteScreenSnapshot fail, sn: {}, id: {}", sn, id);
+ }
+ } else {
+ logger.info("deleteScreenSnapshot not found, sn: {}, id: {}", sn, id);
+ }
+ return Result.ok().message("success");
+ }
}
diff --git a/src/main/java/com/onekeycall/videotablet/entity/ScreenshotInfo.java b/src/main/java/com/onekeycall/videotablet/entity/ScreenshotInfo.java
new file mode 100644
index 0000000..dcbb329
--- /dev/null
+++ b/src/main/java/com/onekeycall/videotablet/entity/ScreenshotInfo.java
@@ -0,0 +1,25 @@
+package com.onekeycall.videotablet.entity;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+@Entity
+@Table(name = "devices_snapshot")
+public class ScreenshotInfo {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id",unique = true, nullable = false)
+ private Long id;
+
+ @Column(name = "sn", unique = true, nullable = false)
+ private String sn;
+
+ @Column(name = "file_name", unique = true, nullable = false)
+ private String file_name;
+
+ @Column(name = "upload_time", unique = true, nullable = false)
+ private Long upload_time;
+}
diff --git a/src/main/java/com/onekeycall/videotablet/filter/JwtAuthenticationFilter.java b/src/main/java/com/onekeycall/videotablet/filter/JwtAuthenticationFilter.java
index b48ca38..027c5e4 100644
--- a/src/main/java/com/onekeycall/videotablet/filter/JwtAuthenticationFilter.java
+++ b/src/main/java/com/onekeycall/videotablet/filter/JwtAuthenticationFilter.java
@@ -77,6 +77,10 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
setUnauthorizedResponse(response, Result.unAuthorized().message("Invalid credentials"));
return; // 重要!验证失败时终止过滤器链
}
+ }else {
+ logger.error("Authorization header format error | Header: " + authorizationHeader);
+ setUnauthorizedResponse(response, Result.unAuthorized().message("Authorization header format error"));
+ return; // 重要!验证失败时终止过滤器链
}
// 如果获取到用户名且当前上下文没有认证信息
@@ -87,7 +91,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
logger.debug("Loaded user authorities: " + user.getAuthorities());
// 验证Token
- if (jwtUtil.validateToken(accessToken, user,deviceId)) {
+ if (jwtUtil.validateToken(accessToken, user, deviceId)) {
// 创建认证令牌
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(
diff --git a/src/main/java/com/onekeycall/videotablet/repository/ScreenshotRepository.java b/src/main/java/com/onekeycall/videotablet/repository/ScreenshotRepository.java
new file mode 100644
index 0000000..f774fdc
--- /dev/null
+++ b/src/main/java/com/onekeycall/videotablet/repository/ScreenshotRepository.java
@@ -0,0 +1,19 @@
+package com.onekeycall.videotablet.repository;
+
+import com.onekeycall.videotablet.entity.ScreenshotInfo;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+public interface ScreenshotRepository extends JpaRepository {
+ List findAllBySn(String sn);
+
+ boolean existsBySnAndId(String sn, Long id);
+
+ @Transactional
+ int deleteAllBySn(String sn);
+
+ @Transactional
+ int deleteBySnAndId(String sn, Long id);
+}
diff --git a/src/main/java/com/onekeycall/videotablet/service/ScreenshotService.java b/src/main/java/com/onekeycall/videotablet/service/ScreenshotService.java
new file mode 100644
index 0000000..57750b4
--- /dev/null
+++ b/src/main/java/com/onekeycall/videotablet/service/ScreenshotService.java
@@ -0,0 +1,48 @@
+package com.onekeycall.videotablet.service;
+
+import com.onekeycall.videotablet.config.CommonConfig;
+import com.onekeycall.videotablet.config.FilePath;
+import com.onekeycall.videotablet.entity.ScreenshotInfo;
+import com.onekeycall.videotablet.repository.ScreenshotRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+@Service
+public class ScreenshotService {
+ private final ScreenshotRepository screenshotRepository;
+
+ @Autowired
+ public ScreenshotService(ScreenshotRepository screenshotRepository) {
+ this.screenshotRepository = screenshotRepository;
+ }
+
+ public List findBySn(String sn) {
+ List screenshotInfos = screenshotRepository.findAllBySn(sn);
+ screenshotInfos.forEach(new Consumer() {
+ @Override
+ public void accept(ScreenshotInfo screenshotInfo) {
+ screenshotInfo.setFile_name(CommonConfig.ROOT_URL + FilePath.getScreenshotPath() + screenshotInfo.getFile_name());
+ }
+ });
+ return screenshotInfos;
+ }
+
+ public void save(ScreenshotInfo screenshotInfo) {
+ screenshotRepository.save(screenshotInfo);
+ }
+
+ public boolean existsBySnAndId(String sn, Long id) {
+ return screenshotRepository.existsBySnAndId(sn, id);
+ }
+
+ public boolean deleteAllBySn(String sn) {
+ return screenshotRepository.deleteAllBySn(sn) > 0;
+ }
+
+ public boolean deleteBySnAndId(String sn, Long id) {
+ return screenshotRepository.deleteBySnAndId(sn, id) > 0;
+ }
+}
diff --git a/src/main/java/com/onekeycall/videotablet/tencent/cos/TransferManagerDemo.java b/src/main/java/com/onekeycall/videotablet/tencent/cos/TransferManagerDemo.java
new file mode 100644
index 0000000..a7ee674
--- /dev/null
+++ b/src/main/java/com/onekeycall/videotablet/tencent/cos/TransferManagerDemo.java
@@ -0,0 +1,441 @@
+package com.onekeycall.videotablet.tencent.cos;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.exception.CosClientException;
+import com.qcloud.cos.exception.CosServiceException;
+import com.qcloud.cos.http.HttpProtocol;
+import com.qcloud.cos.model.CopyObjectRequest;
+import com.qcloud.cos.model.CopyResult;
+import com.qcloud.cos.model.GetObjectRequest;
+import com.qcloud.cos.model.ObjectMetadata;
+import com.qcloud.cos.model.PutObjectRequest;
+import com.qcloud.cos.model.UploadResult;
+import com.qcloud.cos.region.Region;
+import com.qcloud.cos.transfer.Copy;
+import com.qcloud.cos.transfer.Download;
+import com.qcloud.cos.transfer.MultipleFileDownload;
+import com.qcloud.cos.transfer.MultipleFileUpload;
+import com.qcloud.cos.transfer.PersistableDownload;
+import com.qcloud.cos.transfer.PersistableUpload;
+import com.qcloud.cos.transfer.Transfer;
+import com.qcloud.cos.transfer.TransferManager;
+import com.qcloud.cos.transfer.TransferManagerConfiguration;
+import com.qcloud.cos.transfer.TransferProgress;
+import com.qcloud.cos.transfer.Upload;
+
+// TransferManager提供异步的上传文件, 下载文件,copy文件的高级API接口
+// 可以根据文件大小自动的选择上传接口或者copy接口,方便用户使用, 无需自行封装较复杂的分块上传或者分块copy
+public class TransferManagerDemo {
+ private static String secretId = System.getenv("SECRETID");
+ private static String secretKey = System.getenv("SECRETKEY");
+ private static String cosRegion = System.getenv("REGION");
+ private static String bucketName = System.getenv("BUCKET_NAME");
+ public static void main(String[] args) {
+ //multipartUploadWithMetaData();
+ resumableDownloadFile();
+ }
+
+ private static TransferManager createTransferManager() {
+ // 1 初始化用户身份信息(secretId, secretKey)
+ COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
+ // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
+ ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
+ clientConfig.setHttpProtocol(HttpProtocol.https);
+ // 3 生成cos客户端
+ COSClient cosclient = new COSClient(cred, clientConfig);
+
+ ExecutorService threadPool = Executors.newFixedThreadPool(32);
+ // 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
+ TransferManager transferManager = new TransferManager(cosclient, threadPool);
+ return transferManager;
+ }
+
+ // Prints progress while waiting for the transfer to finish.
+ private static void showTransferProgress(Transfer transfer) {
+ System.out.println(transfer.getDescription());
+ do {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ return;
+ }
+ TransferProgress progress = transfer.getProgress();
+ long so_far = progress.getBytesTransferred();
+ long total = progress.getTotalBytesToTransfer();
+ double pct = progress.getPercentTransferred();
+ System.out.printf("[%d / %d] = %.02f%%\n", so_far, total, pct);
+ } while (transfer.isDone() == false);
+ System.out.println(transfer.getState());
+ }
+
+ // 上传文件, 根据文件大小自动选择简单上传或者分块上传。
+ private static void uploadFile() {
+ TransferManager transferManager = createTransferManager();
+
+ String key = "aaa/bbb.txt";
+ File localFile = new File("src/test/resources/len30M.txt");
+
+ PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
+ try {
+ // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
+ long startTime = System.currentTimeMillis();
+ Upload upload = transferManager.upload(putObjectRequest);
+ showTransferProgress(upload);
+ UploadResult uploadResult = upload.waitForUploadResult();
+ long endTime = System.currentTimeMillis();
+ System.out.println("used time: " + (endTime - startTime) / 1000);
+ System.out.println(uploadResult.getETag());
+ System.out.println(uploadResult.getCrc64Ecma());
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+ // 上传文件(上传过程中暂停, 并继续上传)
+ private static void pauseUploadFileAndResume() {
+ TransferManager transferManager = createTransferManager();
+
+ String key = "aaa/bbb.txt";
+ File localFile = new File("src/test/resources/len30M.txt");
+ PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
+ try {
+ // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
+ Upload upload = transferManager.upload(putObjectRequest);
+ Thread.sleep(10000);
+ PersistableUpload persistableUpload = upload.pause();
+ upload = transferManager.resumeUpload(persistableUpload);
+ showTransferProgress(upload);
+ UploadResult uploadResult = upload.waitForUploadResult();
+ System.out.println(uploadResult.getETag());
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+ private static void multipartUploadWithMetaData() {
+ TransferManager transferManager = createTransferManager();
+
+ String key = "aaa/bbb.txt";
+ File localFile = new File("src/test/resources/len20M.txt");
+
+ ObjectMetadata objectMetadata = new ObjectMetadata();
+ Map userMeta = new HashMap();
+ userMeta.put("usermeta", "hello-mult");
+ objectMetadata.setUserMetadata(userMeta);
+
+ PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
+ putObjectRequest.withMetadata(objectMetadata);
+ try {
+ // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
+ long startTime = System.currentTimeMillis();
+ Upload upload = transferManager.upload(putObjectRequest);
+ //showTransferProgress(upload);
+ UploadResult uploadResult = upload.waitForUploadResult();
+ long endTime = System.currentTimeMillis();
+ System.out.println("used time: " + (endTime - startTime) / 1000);
+ System.out.println(uploadResult.getETag());
+ System.out.println(uploadResult.getCrc64Ecma());
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+ // 批量上传
+ private static void uploadDirectory() {
+ TransferManager transferManager = createTransferManager();
+
+ // 设置文件上传到 bucket 之后的前缀目录,设置为 “”,表示上传到 bucket 的根目录
+ String cos_path = "/prefix";
+ // 要上传的文件夹的绝对路径
+ String dir_path = "/to/mydir";
+ // 是否递归上传目录下的子目录,如果是 true,子目录下的文件也会上传,且cos上会保持目录结构
+ Boolean recursive = false;
+
+ try {
+ // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
+ MultipleFileUpload upload = transferManager.uploadDirectory(bucketName, cos_path, new File(dir_path), recursive);
+
+ // 可以选择查看上传进度
+ showTransferProgress(upload);
+
+ // 或者阻塞等待完成
+ upload.waitForCompletion();
+
+ System.out.println("upload directory done.");
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+ // 批量下载
+ private static void downloadDirectory() {
+ TransferManager transferManager = createTransferManager();
+
+ // 设置要下载的对象的前缀(相当于cos上的一个目录),如果设置成 "",则下载整个 bucket。
+ String cos_path = "/prefix";
+ // 要保存下载的文件的文件夹的绝对路径
+ String dir_path = "/to/mydir";
+
+ try {
+ // 返回一个异步结果download, 可同步的调用waitForUploadResult等待download结束.
+ MultipleFileDownload download = transferManager.downloadDirectory(bucketName, cos_path, new File(dir_path));
+
+ // 可以选择查看下载进度
+ showTransferProgress(download);
+
+ // 或者阻塞等待完成
+ download.waitForCompletion();
+
+ System.out.println("download directory done.");
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+ // 将文件下载到本地
+ private static void downLoadFile() {
+ TransferManager transferManager = createTransferManager();
+
+ String key = "aaa/bbb.txt";
+ File downloadFile = new File("src/test/resources/download.txt");
+ GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
+ try {
+ // 返回一个异步结果copy, 可同步的调用waitForCompletion等待download结束, 成功返回void, 失败抛出异常.
+ Download download = transferManager.download(getObjectRequest, downloadFile);
+ download.waitForCompletion();
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+ // 将文件下载到本地(中途暂停并继续开始)
+ private static void pauseDownloadFileAndResume() {
+ TransferManager transferManager = createTransferManager();
+
+ String key = "aaa/bbb.txt";
+ File downloadFile = new File("src/test/resources/download.txt");
+ GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
+ try {
+ // 返回一个异步结果copy, 可同步的调用waitForCompletion等待download结束, 成功返回void, 失败抛出异常.
+ Download download = transferManager.download(getObjectRequest, downloadFile);
+ Thread.sleep(5000L);
+ PersistableDownload persistableDownload = download.pause();
+ download = transferManager.resumeDownload(persistableDownload);
+ showTransferProgress(download);
+ download.waitForCompletion();
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+
+ // copy接口支持根据文件大小自动选择copy或者分块copy
+ // 以下代码展示跨园区拷贝, 即将一个园区的文件拷贝到另一个园区
+ private static void copyFileForDiffRegion() {
+ // 1 初始化用户身份信息(secretId, secretKey)
+ COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
+ // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
+ ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
+ // 3 生成cos客户端
+ COSClient cosclient = new COSClient(cred, clientConfig);
+
+ ExecutorService threadPool = Executors.newFixedThreadPool(32);
+ // 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
+ TransferManager transferManager = new TransferManager(cosclient, threadPool);
+
+ // 要拷贝的bucket region, 支持跨园区拷贝
+ Region srcBucketRegion = new Region("ap-shanghai");
+ // 源bucket, bucket名需包含appid
+ String srcBucketName = "srcBucket-12500000000";
+ // 要拷贝的源文件
+ String srcKey = "aaa/bbb.txt";
+ // 目的bucket, bucket名需包含appid
+ String destBucketName = "destBucket-12500000000";
+ // 要拷贝的目的文件
+ String destKey = "ccc/ddd.txt";
+
+ COSClient srcCOSClient = new COSClient(cred, new ClientConfig(srcBucketRegion));
+ CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, srcBucketName,
+ srcKey, destBucketName, destKey);
+ try {
+ Copy copy = transferManager.copy(copyObjectRequest, srcCOSClient, null);
+ // 返回一个异步结果copy, 可同步的调用waitForCopyResult等待copy结束, 成功返回CopyResult, 失败抛出异常.
+ CopyResult copyResult = copy.waitForCopyResult();
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ srcCOSClient.shutdown();
+ cosclient.shutdown();
+ }
+
+ // copy接口支持根据文件大小自动选择copy或者分块copy
+ // 以下代码展示同园区拷贝, 即将同园区的文件拷贝到另一个园区
+ private static void copyFileForSameRegion() {
+ TransferManager transferManager = createTransferManager();
+ TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
+ transferManagerConfiguration.setMultipartCopyThreshold(20*1024*1024);
+ transferManager.setConfiguration(transferManagerConfiguration);
+
+ // 要拷贝的bucket region, 支持跨园区拷贝
+ Region srcBucketRegion = new Region("ap-beijing-1");
+ // 源bucket, bucket名需包含appid
+ String srcBucketName = "srcBucket-12500000000";
+ // 要拷贝的源文件
+ String srcKey = "aaa/bbb.txt";
+ // 目的bucket, bucket名需包含appid
+ String destBucketName = "destBucket-12500000000";
+ // 要拷贝的目的文件
+ String destKey = "ccc/ddd.txt";
+
+ CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, srcBucketName,
+ srcKey, destBucketName, destKey);
+ try {
+ Copy copy = transferManager.copy(copyObjectRequest);
+ // 返回一个异步结果copy, 可同步的调用waitForCopyResult等待copy结束, 成功返回CopyResult, 失败抛出异常.
+ CopyResult copyResult = copy.waitForCopyResult();
+ System.out.println(copyResult.getCrc64Ecma());
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+
+ private static void copyFileSetMetadata() {
+ // 1 初始化用户身份信息(secretId, secretKey)
+ COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
+ // 2 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224
+ ClientConfig clientConfig = new ClientConfig(new Region(cosRegion));
+ // 3 生成cos客户端
+ COSClient cosclient = new COSClient(cred, clientConfig);
+
+ ClientConfig srcClientConfig = new ClientConfig(new Region("ap-shanghai"));
+ COSClient srcCosclient = new COSClient(cred, srcClientConfig);
+
+ ExecutorService threadPool = Executors.newFixedThreadPool(2);
+ // 传入一个threadpool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池。
+ TransferManager transferManager = new TransferManager(cosclient, threadPool);
+ TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
+ transferManagerConfiguration.setMultipartCopyThreshold(5*1024*1024);
+ transferManager.setConfiguration(transferManagerConfiguration);
+
+ // 要拷贝的bucket region, 支持跨园区拷贝
+ Region srcBucketRegion = new Region("ap-shanghai");
+ // 源bucket, bucket名需包含appid
+ String srcBucketName = "mysrcbucket-123456789";
+ // 要拷贝的源文件
+ String srcKey = "aaa/bbb.txt";
+ // 目的bucket, bucket名需包含appid
+ String destBucketName = "mydestbucekt-123456789";
+ // 要拷贝的目的文件
+ String destKey = "bbb/ccc.txt";
+
+ ObjectMetadata objectMetadata = new ObjectMetadata();
+ Map userMeta = new HashMap();
+ userMeta.put("usermeta", "hello-mult-copy");
+ objectMetadata.setUserMetadata(userMeta);
+
+ CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketRegion, srcBucketName,
+ srcKey, destBucketName, destKey);
+ System.out.println(copyObjectRequest.getDestinationBucketName());
+ copyObjectRequest.setNewObjectMetadata(objectMetadata);
+ try {
+ Copy copy = transferManager.copy(copyObjectRequest, srcCosclient, null);
+ // 返回一个异步结果copy, 可同步的调用waitForCopyResult等待copy结束, 成功返回CopyResult, 失败抛出异常.
+ //showTransferProgress(copy);
+ CopyResult copyResult = copy.waitForCopyResult();
+ System.out.println(copyResult.getCrc64Ecma());
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ cosclient.shutdown();
+ }
+
+ private static void resumableDownloadFile() {
+ TransferManager transferManager = createTransferManager();
+
+ GetObjectRequest getObj = new GetObjectRequest(bucketName, "/path/to/key");
+
+ File dstFile = new File("dstFile");
+ Download download = transferManager.download(getObj, dstFile, true);
+ showTransferProgress(download);
+ try {
+ download.waitForCompletion();
+ } catch (CosServiceException e) {
+ e.printStackTrace();
+ } catch (CosClientException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ transferManager.shutdownNow();
+ }
+}
\ No newline at end of file