0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ファイル受信した後、NASに保存。保存成功まではtempのファイル名。保存成功したら正式なファイル名に変更する。処理失敗したら、tempファイル名の末尾にyyyymmddhhmmssを付与したファイル名に変更

Last updated at Posted at 2024-06-26
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>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?