if (s3FilesExists.size() != 0) { for (String filePath : s3FilesExists) { ...

如果s3FilesExists列表非空,则程序会逐个遍历其内容,对每个filePath,执行删除操作。输出‘删除:’加上filePath的值,然后调用s3Config.delObject方法,传入目标bucketName和当前filePath,以从AmazonS3存储桶中删除相应对象。

如果s3FilesExists的大小不等于0,则遍历s3FilesExists,并在每次迭代时输出"删除:"和filePath的值,并使用s3Config.delObject(toBucketName, filePath)删除该对象。

@RequestMapping("/savePet") public String savePet(Pet pet, @RequestParam(value = "file", required = false) MultipartFile file, RedirectAttributes redirectAttributes) { try { // 如果是编辑操作,先获取原有宠物信息 Pet existingPet = null; if (pet.getId() != null) { existingPet = petService.getPetById(pet.getId()); } if (file != null && !file.isEmpty()) { // 处理文件上传 String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename(); String uploadDir = "D:/uploads/"; File dir = new File(uploadDir); if (!dir.exists()) { dir.mkdirs(); } String filePath = uploadDir + fileName; // 保存文件到服务器 file.transferTo(new File(filePath)); // 设置图片路径到 pet 对象 - 使用相对路径 pet.setPic("/uploads/" + fileName); // 如果编辑时有新文件上传,删除旧图片(可选) if (existingPet != null && existingPet.getPic() != null) { deleteOldImage(existingPet.getPic()); } } else if (existingPet != null) { // 如果没有上传新文件,保持原有图片 pet.setPic(existingPet.getPic()); } // 设置默认状态 if (pet.getPetstatus() == null) { pet.setPetstatus(0); } // 执行数据库操作 if (pet.getId() == null) { petService.addPet(pet); redirectAttributes.addFlashAttribute("message", "宠物添加成功"); } else { petService.updatePet(pet); redirectAttributes.addFlashAttribute("message", "宠物信息更新成功"); } } catch (IOException e) { redirectAttributes.addFlashAttribute("errorMessage", "文件上传失败: " + e.getMessage()); return "redirect:/admin/pet"; } catch (Exception e) { redirectAttributes.addFlashAttribute("errorMessage", "操作失败: " + e.getMessage()); return "redirect:/admin/pet"; } return "redirect:/admin/pet"; }使用该controler时,pic不显示, <c:if test="${not empty pet.pic}"> <img th:if="${pet.pic}" th:src="@{${pet.pic}}" alt="宠物图片" style="width: 100px; height: 100px; object-fit: cover;"> </c:if> <c:if test="${empty pet.pic}"> 无图片 </c:if>解决
10-26
/* * Copyright 2019-2025 Zheng Jie * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package me.zhengjie.service.impl; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.IdUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.zhengjie.config.AmzS3Config; import me.zhengjie.domain.S3Storage; import me.zhengjie.exception.BadRequestException; import me.zhengjie.repository.S3StorageRepository; import me.zhengjie.service.S3StorageService; import me.zhengjie.service.dto.S3StorageQueryCriteria; import me.zhengjie.utils.*; import org.apache.commons.io.IOUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.waiters.WaiterResponse; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.*; import software.amazon.awssdk.services.s3.waiters.S3Waiter; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*; /** * @description 服务实现 * @author Zheng Jie * @date 2025-06-25 **/ @Slf4j @Service @RequiredArgsConstructor public class S3StorageServiceImpl implements S3StorageService { private final S3Client s3Client; private final AmzS3Config amzS3Config; private final S3StorageRepository s3StorageRepository; @Override public S3Storage getById(Long id) { return s3StorageRepository.findById(id).orElse(null); } @Override public PageResult<S3Storage> queryAll(S3StorageQueryCriteria criteria, Pageable pageable){ Page<S3Storage> page = s3StorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); return PageUtil.toPage(page); } @Override public List<S3Storage> queryAll(S3StorageQueryCriteria criteria){ return s3StorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); } @Override @Transactional(rollbackFor = Exception.class) public void deleteAll(List<Long> ids) { // 检查桶是否存在 String bucketName = amzS3Config.getDefaultBucket(); if (!bucketExists(bucketName)) { throw new BadRequestException("存储桶不存在,请检查配置或权限。"); } // 遍历 ID 列表,删除对应的文件和数据库记录 for (Long id : ids) { String filePath = s3StorageRepository.selectFilePathById(id); if (filePath == null) { System.err.println("未找到 ID 为 " + id + " 的文件记录,无法删除。"); continue; } try { // 创建 DeleteObjectRequest,指定存储桶和文件键 DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder() .bucket(bucketName) .key(filePath) .build(); // 调用 deleteObject 方法 s3Client.deleteObject(deleteObjectRequest); // 删除数据库数据 s3StorageRepository.deleteById(id); } catch (S3Exception e) { // 处理 AWS 特定的异常 log.error("从 S3 删除文件时出错: {}", e.awsErrorDetails().errorMessage(), e); } } } @Override public S3Storage upload(MultipartFile file) { String bucketName = amzS3Config.getDefaultBucket(); // 检查存储桶是否存在 if (!bucketExists(bucketName)) { log.warn("存储桶 {} 不存在,尝试创建...", bucketName); if (createBucket(bucketName)){ log.info("存储桶 {} 创建成功。", bucketName); } else { throw new BadRequestException("存储桶创建失败,请检查配置或权限。"); } } // 获取文件名 String originalName = file.getOriginalFilename(); if (StringUtils.isBlank(originalName)) { throw new IllegalArgumentException("文件名不能为空"); } // 生成存储路径和文件名 String folder = DateUtil.format(new Date(), amzS3Config.getTimeformat()); String fileName = IdUtil.simpleUUID() + "." + FileUtil.getExtensionName(originalName); String filePath = folder + "/" + fileName; // 构建上传请求 PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket(amzS3Config.getDefaultBucket()) .key(filePath) .build(); // 创建 S3Storage 实例 S3Storage s3Storage = new S3Storage(); try { // 上传文件到 S3 s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(file.getInputStream(), file.getSize())); // 设置 S3Storage 属性 s3Storage.setFileMimeType(FileUtil.getMimeType(originalName)); s3Storage.setFileName(originalName); s3Storage.setFileRealName(fileName); s3Storage.setFileSize(FileUtil.getSize(file.getSize())); s3Storage.setFileType(FileUtil.getExtensionName(originalName)); s3Storage.setFilePath(filePath); // 保存入库 s3StorageRepository.save(s3Storage); } catch (IOException e) { throw new RuntimeException(e); } // 设置地址 return s3Storage; } @Override public void download(List<S3Storage> all, HttpServletResponse response) throws IOException { List<Map<String, Object>> list = new ArrayList<>(); for (S3Storage s3Storage : all) { Map<String,Object> map = new LinkedHashMap<>(); map.put("文件名称", s3Storage.getFileName()); map.put("真实存储的名称", s3Storage.getFileRealName()); map.put("文件大小", s3Storage.getFileSize()); map.put("文件MIME 类型", s3Storage.getFileMimeType()); map.put("文件类型", s3Storage.getFileType()); map.put("文件路径", s3Storage.getFilePath()); map.put("创建者", s3Storage.getCreateBy()); map.put("更新者", s3Storage.getUpdateBy()); map.put("创建日期", s3Storage.getCreateTime()); map.put("更新时间", s3Storage.getUpdateTime()); list.add(map); } FileUtil.downloadExcel(list, response); } public Map<String, String> privateDownload(Long id) { S3Storage storage = s3StorageRepository.findById(id).orElse(null); if (storage == null) { throw new BadRequestException("文件不存在或已被删除"); } // 创建 GetObjectRequest,指定存储桶和文件键 GetObjectRequest getObjectRequest = GetObjectRequest.builder() .bucket(amzS3Config.getDefaultBucket()) .key(storage.getFilePath()) .build(); String base64Data; // 使用 try-with-resources 确保流能被自动关闭 // s3Client.getObject() 返回一个 ResponseInputStream,它是一个包含S3对象数据的输入流 try (ResponseInputStream<GetObjectResponse> s3InputStream = s3Client.getObject(getObjectRequest)) { // 使用 IOUtils.toByteArray 将输入流直接转换为字节数组 byte[] fileBytes = IOUtils.toByteArray(s3InputStream); // 使用 Java 内置的 Base64 编码器将字节数组转换为 Base64 字符串 base64Data = Base64.getEncoder().encodeToString(fileBytes); } catch (S3Exception e) { // 处理 AWS 特定的异常 throw new BadRequestException("从 S3 下载文件时出错: " + e.awsErrorDetails().errorMessage()); } catch (IOException e) { // 处理通用的 IO 异常 (IOUtils.toByteArray 可能会抛出) throw new BadRequestException("读取 S3 输入流时出错: " + e.getMessage()); } // 构造返回数据 Map<String, String> responseData = new HashMap<>(); // 文件名 responseData.put("fileName", storage.getFileName()); // 文件类型 responseData.put("fileMimeType", storage.getFileMimeType()); // 文件内容 responseData.put("base64Data", base64Data); return responseData; } /** * 检查云存储桶是否存在 * @param bucketName 存储桶名称 */ @SuppressWarnings({"all"}) private boolean bucketExists(String bucketName) { try { HeadBucketRequest headBucketRequest = HeadBucketRequest.builder() .bucket(bucketName) .build(); s3Client.headBucket(headBucketRequest); return true; } catch (S3Exception e) { // 如果状态码是 404 (Not Found), 说明存储桶不存在 if (e.statusCode() == 404) { log.error("存储桶 &#39;{}&#39; 不存在。", bucketName); return false; } // 其他异常 (如 403 Forbidden) 说明存在问题,但不能断定它不存在 throw new BadRequestException("检查存储桶时出错: " + e.awsErrorDetails().errorMessage()); } } /** * 创建云存储桶 * @param bucketName 存储桶名称 */ private boolean createBucket(String bucketName) { try { // 使用 S3Waiter 等待存储桶创建完成 S3Waiter s3Waiter = s3Client.waiter(); CreateBucketRequest bucketRequest = CreateBucketRequest.builder() .bucket(bucketName) .acl(BucketCannedACL.PRIVATE) .build(); s3Client.createBucket(bucketRequest); // 等待直到存储桶创建完成 HeadBucketRequest bucketRequestWait = HeadBucketRequest.builder() .bucket(bucketName) .build(); // 使用 WaiterResponse 等待存储桶存在 WaiterResponse<HeadBucketResponse> waiterResponse = s3Waiter.waitUntilBucketExists(bucketRequestWait); waiterResponse.matched().response().ifPresent(response -> log.info("存储桶 &#39;{}&#39; 创建成功,状态: {}", bucketName, response.sdkHttpResponse().statusCode()) ); } catch (BucketAlreadyOwnedByYouException e) { log.warn("存储桶 &#39;{}&#39; 已经被您拥有,无需重复创建。", bucketName); } catch (S3Exception e) { throw new BadRequestException("创建存储桶时出错: " + e.awsErrorDetails().errorMessage()); } return true; } } 增加一个方法,生成一个预签名url,
10-01
内容概要:本文设计了一种基于PLC的全自动洗衣机控制系统内容概要:本文设计了一种,采用三菱FX基于PLC的全自动洗衣机控制系统,采用3U-32MT型PLC作为三菱FX3U核心控制器,替代传统继-32MT电器控制方式,提升了型PLC作为系统的稳定性与自动化核心控制器,替代水平。系统具备传统继电器控制方式高/低水,实现洗衣机工作位选择、柔和过程的自动化控制/标准洗衣模式切换。系统具备高、暂停加衣、低水位选择、手动脱水及和柔和、标准两种蜂鸣提示等功能洗衣模式,支持,通过GX Works2软件编写梯形图程序,实现进洗衣过程中暂停添加水、洗涤、排水衣物,并增加了手动脱水功能和、脱水等工序蜂鸣器提示的自动循环控制功能,提升了使用的,并引入MCGS组便捷性与灵活性态软件实现人机交互界面监控。控制系统通过GX。硬件设计包括 Works2软件进行主电路、PLC接梯形图编程线与关键元,完成了启动、进水器件选型,软件、正反转洗涤部分完成I/O分配、排水、脱、逻辑流程规划水等工序的逻辑及各功能模块梯设计,并实现了大形图编程。循环与小循环的嵌; 适合人群:自动化套控制流程。此外、电气工程及相关,还利用MCGS组态软件构建专业本科学生,具备PL了人机交互C基础知识和梯界面,实现对洗衣机形图编程能力的运行状态的监控与操作。整体设计涵盖了初级工程技术人员。硬件选型、; 使用场景及目标:I/O分配、电路接线、程序逻辑设计及组①掌握PLC在态监控等多个方面家电自动化控制中的应用方法;②学习,体现了PLC在工业自动化控制中的高效全自动洗衣机控制系统的性与可靠性。;软硬件设计流程 适合人群:电气;③实践工程、自动化及相关MCGS组态软件与PLC的专业的本科生、初级通信与联调工程技术人员以及从事;④完成PLC控制系统开发毕业设计或工业的学习者;具备控制类项目开发参考一定PLC基础知识。; 阅读和梯形图建议:建议结合三菱编程能力的人员GX Works2仿真更为适宜。; 使用场景及目标:①应用于环境与MCGS组态平台进行程序高校毕业设计或调试与运行验证课程项目,帮助学生掌握PLC控制系统的设计,重点关注I/O分配逻辑、梯形图与实现方法;②为工业自动化领域互锁机制及循环控制结构的设计中类似家电控制系统的开发提供参考方案;③思路,深入理解PL通过实际案例理解C在实际工程项目PLC在电机中的应用全过程。控制、时间循环、互锁保护、手动干预等方面的应用逻辑。; 阅读建议:建议结合三菱GX Works2编程软件和MCGS组态软件同步实践,重点理解梯形图程序中各环节的时序逻辑与互锁机制,关注I/O分配与硬件接线的对应关系,并尝试在仿真环境中调试程序以加深对全自动洗衣机控制流程的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值