快来薅羊毛:轻量云对象存储
随着社交媒体和图片分享平台的广泛应用,图床(即图片托管服务)成为了开发者和内容创作者不可或缺的一部分。图床允许用户将图片上传到云端存储,并通过 URL 进行访问,减少了用户设备上的存储空间占用,同时提供了高效的图片管理和访问方式。腾讯云的轻量对象存储(COS)为开发者提供了一个简单且高效的图床解决方案,本文将介绍如何使用腾讯云 COS 构建一个完整的在线图床功能。
图床(Image Hosting Service)是指将图片存储在云端服务器上,通过 HTTP 或 HTTPS 协议提供图片访问链接的服务。图床的核心功能包括:通过图床,用户无需再将图片存储在本地服务器上,大大提高了系统的扩展性和图片访问速度。
腾讯云 COS(Cloud Object Storage)是腾讯云提供的一种云存储服务,适合存储海量非结构化数据,如图片、视频、日志等。其具备以下特点:
一个完整的在线图床功能需要满足以下需求:在实现这些需求之前,我们需要进行一些基本的准备工作。
首先,前往 腾讯云官网 注册一个腾讯云账号。如果已有账号,可以直接登录。
为了在 Java 项目中使用腾讯云 COS,需要导入腾讯云的 SDK。以下是添加依赖的方式。
在 pom.xml
文件中加入以下依赖:
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.54</version>
</dependency>
在 application.properties
或 application.yml
中配置腾讯云 COS 相关参数:
tencent:
cos:
secretId: xxxxxxx
secretKey: xxxxxxxxxxxxxxxxx
region: ap-nanjing
bucketName: number-89757-1259242531
首先,我们需要创建一个实体类 Image
来存储图床中的图片信息,包括图片的 URL、文件名、文件大小等。
package com.example.demo.entity;
// 响应 DTO
public class ResponseDto {
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
接下来,我们创建一个 CosService
类来封装所有与腾讯云 COS 相关的操作,包括上传、删除、获取文件等功能。
package com.example.demo.service;
import com.example.demo.controller.CosImageController;
import com.example.demo.entity.ResponseDto;
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.region.Region;
import com.qcloud.cos.model.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@Service
public class CosService {
@Value("${tencent.cos.secretId}")
private String secretId;
@Value("${tencent.cos.secretKey}")
private String secretKey;
@Value("${tencent.cos.region}")
private String region;
@Value("${tencent.cos.bucketName}")
private String bucketName;
/**
* 上传文件到 COS
*
* @param file 上传的文件
* @param key 上传到 COS 的对象键
* @return 文件的 URL 地址
* @throws IOException
*/
public String uploadFile(File file, String key) throws IOException {
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
ClientConfig clientConfig = new ClientConfig(new Region(region));
COSClient cosClient = new COSClient(cred, clientConfig);
// // 创建上传请求
// PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, file);
// // 执行上传
// cosClient.putObject(putObjectRequest);
FileInputStream fileInputStream = new FileInputStream(file);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, fileInputStream, new ObjectMetadata());
cosClient.putObject(putObjectRequest);
// 生成文件的 URL 地址
return "https://" + bucketName + ".cos." + region + ".myqcloud.com/" + key;
}
/**
* 删除 COS 中的文件
*
* @param key 文件的对象键
*/
public void deleteFile(String key) {
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
ClientConfig clientConfig = new ClientConfig(new Region(region));
COSClient cosClient = new COSClient(cred, clientConfig);
cosClient.deleteObject(bucketName, key);
}
/**
* 获取 COS 中所有文件的列表
*
* @return 文件列表
*/
public List<ResponseDto> listFiles() {
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
ClientConfig clientConfig = new ClientConfig(new Region(region));
COSClient cosClient = new COSClient(cred, clientConfig);
ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
.withBucketName(bucketName)
.withPrefix(""); // 可以设置前缀来过滤文件
ObjectListing objectListing = cosClient.listObjects(listObjectsRequest);
List<COSObjectSummary> aa = objectListing.getObjectSummaries();
List<ResponseDto> result = new ArrayList<>();
for (COSObjectSummary vv :aa){
ResponseDto dd = new ResponseDto();
GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, vv.getKey());
// req.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)); // 设置URL有效期为1小时
URL signedUrl = cosClient.generatePresignedUrl(req);
dd.setUrl(signedUrl.toString());
result.add(dd);
}
return result;
}
/**
* 转换 MultipartFile 为 File 对象
*
* @param file 上传的 MultipartFile 文件
* @return 转换后的 File 对象
* @throws IOException
*/
public File convertMultiPartToFile(MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
file.transferTo(convFile);
return convFile;
}
/**
* 关闭 COS 客户端
*/
public void shutdown() {
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
ClientConfig clientConfig = new ClientConfig(new Region(region));
COSClient cosClient = new COSClient(cred, clientConfig);
cosClient.shutdown();
}
}
控制器 ImageController
处理前端的请求,例如上传图片、列出图片、删除图片等。
package com.example.demo.controller;
import com.example.demo.entity.ResponseDto;
import com.example.demo.service.CosService;
import com.qcloud.cos.model.COSObjectSummary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.ResponseEntity;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
@Controller
public class CosImageController {
@Autowired
private CosService cosService; // 调用 COS 服务
// 图片存储路径
private static final String UPLOAD_DIR = "src/main/resources/static/uploads/";
@GetMapping("/")
public String ocrPage() {
return "cos"; // 返回上传页面视图
}
// 上传图片
@PostMapping("/image/upload")
public String uploadImage(@RequestParam("file") MultipartFile file) throws IOException {
// 将上传的文件保存到 COS
// 确保上传目录存在
Path uploadPath = Paths.get(UPLOAD_DIR);
if (!Files.exists(uploadPath)) {
Files.createDirectories(uploadPath);
}
// 获取文件输入流并存储文件
Path filePath = uploadPath.resolve(file.getOriginalFilename());
try (InputStream inputStream = file.getInputStream()) {
Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
}
try {
String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
// String fileUrl = cosService.uploadFile(convertMultiPartToFile(file), fileName);
String fileUrl = cosService.uploadFile(filePath.toFile(), fileName);
System.out.printf(fileUrl);
} catch (Exception e) {
e.printStackTrace();
}
return "redirect:/";
}
// 获取已上传的图片列表
@GetMapping("/image/list")
@ResponseBody
public List<ResponseDto> getImageList() {
// 这里假设已经存储了图片的 URL 和 ID
List<ResponseDto> sss = cosService.listFiles();
return sss; // 你可以从数据库或 COS 获取图片信息
}
// 删除图片
@DeleteMapping("/image/delete/{id}")
public ResponseEntity<?> deleteImage(@PathVariable String id) {
// 根据 ID 删除文件
cosService.deleteFile(id); // 你可以根据文件 ID 从 COS 删除文件
return ResponseEntity.ok().build();
}
// 辅助方法:转换 MultipartFile 为 File
private File convertMultiPartToFile(MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
file.transferTo(convFile);
return convFile;
}
// 图片信息 DTO
public static class ImageDto {
private String id;
private String url;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
前端部分实现图床的用户界面,支持图片上传和展示。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图床管理</title>
<!-- 引入 Bootstrap 样式 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.image-preview {
max-width: 100px;
max-height: 100px;
object-fit: cover;
}
</style>
</head>
<body>
<div class="container mt-5">
<h1 class="mb-4">图床管理</h1>
<!-- 图片上传部分 -->
<div class="mb-4">
<h3>上传图片</h3>
<form action="/image/upload" method="post" enctype="multipart/form-data">
<input type="file" class="form-control" name="file" required>
<button type="submit" class="btn btn-primary">上传</button>
</form>
</div>
<!-- 已上传的图片列表 -->
<h3>已上传图片</h3>
<div id="imageList" class="row"></div>
</div>
<!-- 引入 jQuery 和 Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
// 加载已上传的图片列表
function loadImageList() {
$.ajax({
url: '/image/list', // 后端获取图片列表的接口
type: 'GET',
success: function (images) {
$('#imageList').empty(); // 清空当前列表
images.forEach(function (image) {
$('#imageList').append(`
<div class="col-md-3 mb-3">
<div class="card">
<img src="${image.url}" class="card-img-top" alt="Image" style="height: 150px; object-fit: cover;">
<div class="card-body">
<a href="${image.url}" target="_blank" class="btn btn-primary btn-sm">查看</a>
<button class="btn btn-danger btn-sm delete-btn" data-id="${image.id}">删除</button>
</div>
</div>
</div>
`);
});
},
error: function (xhr, status, error) {
alert("加载图片列表失败:" + error);
}
});
}
// 删除图片
$(document).on('click', '.delete-btn', function () {
var imageId = $(this).data('id');
$.ajax({
url: '/image/delete/' + imageId, // 后端删除图片的接口
type: 'DELETE',
success: function () {
loadImageList(); // 更新图片列表
},
error: function (xhr, status, error) {
alert("删除失败:" + error);
}
});
});
// 初始化时加载图片列表
loadImageList();
</script>
</body>
</html>
我们使用了 Spring Boot 构建后端,腾讯云 COS 作为存储服务,并实现了图片上传、删除和展示等功能。通过前端 HTML 页面,我们实现了图片上传和查看功能。通过这种方式,我们不仅可以实现一个高效、可靠的图床系统,还能够充分利用腾讯云的云存储优势,提高系统的性能和可扩展性。
当然,在实际的项目开发过程中,我们也可以使用腾讯云对象存储有效减轻轻量应用服务器的功能压力,提升应用性能和稳定性。COS提供了高可靠性、高可用性和低成本的数据存储解决方案,适用于各种规模的应用场景。
就是现在兄弟们,轻量应用服务器*限时秒杀,一年仅需28!!!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。