?上傳文件的基本操作
<form action="/upload" method="post" enctype="multipart/form-data"> <h1>登錄</h1> 姓名:<input type="text" name="username" required><br> 年齡:<input type="text" name="age" required><br> 頭像:<input type="file" name="file" required><br> <input type="submit" value="提交">
</form>
// Java接收前端發來的文件@RestController
public class UploadController {private static final ch.qos.logback.classic.Logger log = (Logger) LoggerFactory.getLogger(UploadController.class);@PostMapping(path = "/upload")public Result upload(String username, Integer age, MultipartFile file){log.info("接收參數:" + username + age + file);return Result.success();}
}
?注意:springboot項目啟動后,打開這個index.html的頁面要輸入:localhost:8080/index.html
接下來通過斷點調試獲取查看前端發送過來的文件?
?文件的”到此一游“:該文件所在的路徑的文件夾是個臨時文件夾,運行完畢后這個文件夾里的內容清空
?前端上傳文件本地存儲
@PostMapping("/upload")public Result upload(String name, Integer age, MultipartFile file) throws IOException {// 記錄接收到的參數,包括姓名、年齡和文件log.info("接收參數: {}, {}, {}", name, age, file);// 獲取上傳文件的原始文件名String originalFilename = file.getOriginalFilename();// 將文件保存到指定路徑(D:/images/)并命名為原始文件名file.transferTo(new File( "D:/idea/javacode/web/Getdata/" + originalFilename));// 返回成功結果return Result.success();}
文件上傳還存在一個要考慮的問題:如果兩次提交的是不一樣的文件,但是文件名稱一樣,那么第二次提交的圖片會把第一次提交的文件給替換(覆蓋)因此可以使用UUID命名來解決。
生成UUID
import java.util.UUID; public class UUIDExample { public static void main(String[] args) { // 生成一個隨機UUID UUID uuid = UUID.randomUUID(); // 輸出UUID System.out.println("生成的UUID: " + uuid.toString()); }
}
使用UUID解決以上問題
?
@PostMapping("/upload")
public Result upload(String name, Integer age, MultipartFile file) throws IOException { // 記錄接收到的參數,包括姓名、年齡和文件 log.info("接收參數: {}, {}, {}", name, age, file); // 獲取上傳文件的原始文件名,例如 "1.jpg" 或 "22.2.2.2.png" String originalFilename = file.getOriginalFilename(); // 獲取文件擴展名,從最后一個點后開始截取 String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); // 生成新的文件名,使用UUID并加上文件擴展名 String newFileName = UUID.randomUUID().toString() + extension; // 將文件保存到指定路徑(D:/images/)并命名為新的文件名 file.transferTo(new File("D:/images/" + newFileName)); // 返回成功結果 return Result.success();
}
file.transferTo(new File("D:/idea/javacode/web/Getdata/" + newFileName));
這個代碼的路徑最后一定要寫個“/”,使得文件保存在那個文件夾下。
上傳文件大小限制
默認上傳文件的最大大小為1MB,超過該大小需要在配置文件配置
servlet: multipart:
# 最大單個文件大小 max-file-size: 10MB
# 最大請求大小(包括所有文件和表單數據) max-request-size: 100MB
阿里云OSS
阿里云對象存儲oss(object Storage Service),是一款海量、安全、低成本、高可靠的云存儲服務。使用oss
您可以通過網絡隨時存儲和調用包括文本、圖片、音頻和視頻等在內的各種文件。
?具體怎么配看:視頻https://www.bilibili.com/video/BV1yGydYEE3H?spm_id_from=333.788.videopod.episodes&vd_source=3c46a0d84476a55380be0c2ddd012af1&p=106
配置好相關密鑰等配置后,創建bucket。接下來可以通過Java代碼將自己電腦本地的文件上傳到阿里云。
添加好下面的依賴
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version>
</dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version>
</dependency>
<dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.3</version>
</dependency>
?具體的上傳文件的代碼
public static void main(String[] args) throws com.aliyuncs.exceptions.ClientException {/*** 基礎配置:連接服務并驗證個人身份*/// Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。String endpoint = "https://oss-cn-shenzhen.aliyuncs.com";// 從環境變量中獲取訪問憑證。運行本代碼示例之前,請確保已設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填寫Bucket名稱,例如examplebucket。String bucketName = "q-buckets";/*** 配置具體文件上傳信息*/// 填寫Object完整路徑,完整路徑中不能包含Bucket名稱,例如exampledir/exampleobject.txt。String objectName = "ph.webp"; // 可以修改名字// 填寫本地文件的完整路徑,例如D:\\localpath\\examplefile.txt。// 如果未指定本地路徑,則默認從示例程序所屬項目對應本地路徑中上傳文件。String filePath= "D:\\Mycode\\webcode\\imag\\nu.webp";// 創建OSSClient實例。OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);try {// 創建PutObjectRequest對象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));// 如果需要上傳時設置存儲類型和訪問權限,請參考以下示例代碼。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上傳文件。PutObjectResult result = ossClient.putObject(putObjectRequest);} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}
這樣就可以在自己阿里云的bucket里面看到上傳的文件?
參考:后端之路?
文件上傳操作整合為工具類并在Controller中使用
具體代碼如下
@Component // 方便依賴注入
public class AliyunOSSOperation { // 指定阿里云OSS的服務地址,這里是深圳區域的地址 private String endpoint = "https://oss-cn-shenzhen.aliyuncs.com"; // 指定要上傳到的存儲桶名稱 private String bucketName = "lwq-buckets"; // 指定阿里云的區域,這里是深圳區域 private String region = "cn-shenzhen"; /** * 上傳文件到阿里云OSS * @param content 文件的字節數組內容 * @param originalFilename 原始文件名,用于生成新的文件名 * @return 上傳后文件的訪問路徑 * @throws Exception 可能拋出的異常 */ public String upload(byte[] content, String originalFilename) throws Exception { // 從環境變量中獲取訪問密鑰,確保在運行代碼前設置環境變量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // 獲取object對象路徑,例如2024/06/21.png。Object類型中不能包含Bucket名稱 String dir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM")); // 生成一個新的文件名,使用UUID確保唯一性,并保留原始文件的擴展名 String newFileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(".")); String objectName = dir + "/" + newFileName; // 生成完整的對象名稱 // 創建OSSClient實例 ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); // 設置簽名版本為V4 // 使用OSSClientBuilder創建OSS客戶端實例,配置包括端點、憑證提供者、客戶端配置和區域 OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // 上傳文件內容到指定的存儲桶和對象路徑 ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content)); } finally { // 確保無論上傳是否成功,都會關閉OSS客戶端 ossClient.shutdown(); } // 生成并返回文件的完整訪問路徑 return endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + objectName; }
}
使用該類?
@Autowired // 自動注入AliyunOSSOperator實例
private AliyunOSSOperator aliyunOSSOperator; @PostMapping("/upload") // 定義一個POST請求處理方法,映射到/upload路徑
public Result upload(MultipartFile file) throws Exception { // 記錄上傳文件的原始文件名到日志 log.info("文件上傳: {}", file.getOriginalFilename()); // 調用aliyunOSSOperator的upload方法,將文件字節和文件名上傳到OSS String url = aliyunOSSOperator.upload(file.getBytes(), file.getOriginalFilename()); // 記錄文件上傳后返回的URL到日志 log.info("文件上傳OSS, url: {}", url); // 返回上傳結果,包含文件的訪問URL return Result.success(url);
}
這樣上傳到阿里云的文件以年月劃分了文件夾?
參數配置進一步優化
- 指將一些需要靈活變化的參數,配置在配置文件中,然后通過 @Value 注解來注入外部配置的屬性。
-
aliyun: oss: endpoint: https://oss-cn-beijing.aliyuncs.com bucketName: java-ai region: cn-beijing
以上配置信息配置在yml文件中
-
@Value("${aliyun.oss.endpoint}") private String endpoint; @Value("${aliyun.oss.bucketName}") private String bucketName; @Value("${aliyun.oss.region}") private String region;