javaoracle-cloud-infrastructureobject-storageoci-java-sdk

Upload a MultipartFile to a Oracle ObjectStorage


I have a Rest enpoint that accept a list of MultipartFile like this:

@CrossOrigin(origins = "*", methods = {RequestMethod.POST})
@PostMapping(value = "/files", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody
ResponseEntity<UploadFileResponse> uploadDocuments(@RequestPart("files") List<MultipartFile> files) throws InfoNotFoundException, IOException {
    log.info("Upload Documents controller");
    if (files == null || files.isEmpty()) {
        throw new RuntimeException("You must select at least one file for uploading");
    }

    UploadFileResponse uploadFileResponse = service.uploadFiles(files);

    ResponseEntity<UploadFileResponse> response = new ResponseEntity<UploadFileResponse>(uploadFileResponse, HttpStatus.OK);
    return response;
}

This is calling a service that has call a method inside to save the information in a ObjectStorage from oracle, like this:

public void upload(MultipartFile file) throws Exception {

    HSAClientConfiguration conf = new HSAClientConfiguration();

    UploadObject app = new UploadObject();

    String fileName = "oci/oci_api_key.pem";
    InputStream is = app.getFileFromResourceAsStream(fileName);

    String result = IOUtils.toString(is, StandardCharsets.UTF_8);

    log.info("Authenticating...");
    AuthenticationDetailsProvider authenticationDetailsProvider =
            SimpleAuthenticationDetailsProvider.builder()
                    .tenantId(conf.getTenantId())
                    .userId(conf.getUserId())
                    .fingerprint(conf.getFingerprint())
                    .privateKeySupplier(new StringPrivateKeySupplier(result))
                    .build();

    ObjectStorage client = new ObjectStorageClient(authenticationDetailsProvider);
    client.setRegion(Region.EU_FRANKFURT_1);

    //Construccion del nombre del archivo.
    String fecha = DateUtil.convertToYYYYMM(Timestamp.from(Instant.now()));
    String objectName = fecha + "/" + file.getOriginalFilename();
    log.info("Loading the file to Object Storage with name: " + objectName);

    //Convertir el fichero para pasar en el putObject
    InputStream inputStream = file.getInputStream();


    log.info("Creating the source object to send");
    PutObjectRequest putObjectRequest =
            PutObjectRequest.builder()
                    .namespaceName(conf.getNameSpace())
                    .bucketName(conf.getBucket())
                    .objectName(objectName)
                    .contentLength(file.getSize())
                    .putObjectBody(inputStream)
                    .build();
    client.putObject(putObjectRequest);

    PutObjectResponse putObjectResponse = client.putObject(putObjectRequest);
    System.out.println("Response: " + putObjectRequest);

}

If instead of Multipart, I pass to this code the Inputstream of a file in the system, it will be save correctly. But when I use the MultipartFile, I recevie an error from the RestClient like this:

com.oracle.bmc.http.internal.RestClient  : Error calling available on the stream to get the available number of bytes

Look like this is produce in the clases from oracle that try to serialize the object. I don't know why. Does anyone know how to serialize a InputStream or deal with this?

Thanks


Solution

  • It was a stupid problem with the response that try to serialize the InputStream. If you remove PutObjectResponse putObjectResponse = client.putObject(putObjectRequest); The code works smooth.

    Enjoy it!