import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
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.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
@Controller
public class FileUploadController {
private static final String NAS_DIRECTORY = "/path/to/nas"; // NASのディレクトリパスを指定
@PostMapping("/upload")
public ResponseEntity<String> handleFileUpload(HttpServletRequest request) {
try {
// try-with-resourcesを使ってInputStreamを処理
try (InputStream inputStream = request.getInputStream()) {
byte[] fileData = inputStream.readAllBytes();
// fileDataの処理をここに書く
} catch (IOException e) {
// エラーハンドリング
e.printStackTrace();
}
// Content-TypeとContent-Dispositionヘッダーを取得
String contentType = request.getContentType();
String contentDisposition = request.getHeader("Content-Disposition");
// ファイル名を抽出
String originalFileName = extractFileName(contentDisposition);
String tempFileName = UUID.randomUUID().toString(); // 一時ファイル名を生成
// 一時ファイルに保存
Path tempFilePath = saveTempFile(fileData, tempFileName);
// ファイルを連携先に送信
sendFileToDestination(fileData, contentType, originalFileName);
// 一時ファイルを正式なファイル名に変更
Path finalFilePath = Paths.get(NAS_DIRECTORY, originalFileName);
Files.move(tempFilePath, finalFilePath);
return ResponseEntity.created(finalFilePath.toUri()).body("File uploaded and sent successfully: " + originalFileName);
} catch (Exception e) {
// 一時ファイル名の末尾にタイムスタンプを付与してリネーム
handleFailedUpload(tempFilePath);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to upload file: " + e.getMessage());
}
}
private Path saveTempFile(byte[] fileData, String tempFileName) throws IOException {
Path tempFilePath = Paths.get(NAS_DIRECTORY, tempFileName);
try (FileOutputStream fos = new FileOutputStream(tempFilePath.toFile())) {
fos.write(fileData);
}
return tempFilePath;
}
private void handleFailedUpload(Path tempFilePath) {
try {
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
Path failedFilePath = Paths.get(tempFilePath.toString() + timestamp);
Files.move(tempFilePath, failedFilePath);
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendFileToDestination(byte[] fileData, String contentType, String fileName) throws IOException, InterruptedException {
// 連携先のURL
String destinationUrl = "http://example.com/destination";
// HttpClientを使用してファイルを送信
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(destinationUrl))
.header("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
.POST(ofMimeMultipartData(fileData, contentType, fileName))
.build();
client.send(request, HttpResponse.BodyHandlers.ofString());
}
private HttpRequest.BodyPublisher ofMimeMultipartData(byte[] fileData, String contentType, String fileName) {
var byteArrayOutputStream = new ByteArrayOutputStream();
var writer = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8), true);
// バウンダリを設定
String boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW";
writer.append("--" + boundary).append("\r\n");
writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"").append("\r\n");
writer.append("Content-Type: " + contentType).append("\r\n");
writer.append("\r\n").flush();
try {
byteArrayOutputStream.write(fileData);
} catch (IOException e) {
e.printStackTrace();
}
writer.append("\r\n").flush();
writer.append("--" + boundary + "--").append("\r\n");
return HttpRequest.BodyPublishers.ofByteArray(byteArrayOutputStream.toByteArray());
}
private String extractFileName(String contentDisposition) {
if (contentDisposition != null) {
String[] parts = contentDisposition.split(";");
for (String part : parts) {
if (part.trim().startsWith("filename")) {
return part.split("=")[1].trim().replace("\"", "");
}
}
}
return "unknown";
}
}
設定
アップロードするファイルごとの最大サイズ 。デフォルトは「1MB」
spring.servlet.multipart.max-file-size
Multipartリクエスト全体の最大サイズを指定します。デフォルトは「10MB」
spring.servlet.multipart.max-request-size
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<context-param>
<param-name>spring.servlet.multipart.max-file-size</param-name>
<param-value>2MB</param-value>
</context-param>
<context-param>
<param-name>spring.servlet.multipart.max-request-size</param-name>
<param-value>2MB</param-value>
</context-param>
</web-app>
pom.xml
<dependencies>
<!-- Spring Web MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- HTTP Client for Java 11 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>
</dependencies>