com.evrythng.java.wrapper.util.FileUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.evrythng.java.wrapper.util.FileUtils.java

Source

/*
 * (c) Copyright Reserved EVRYTHNG Limited 2016. All rights reserved.
 * Use of this material is subject to license.
 * Copying and unauthorised use of this material strictly prohibited.
 */
package com.evrythng.java.wrapper.util;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

/**
 * This class contains utility methods to upload files.
 */
public class FileUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);

    public static final String X_AMZ_ACL_HEADER_NAME = "x-amz-acl";
    public static final String X_AMZ_ACL_HEADER_VALUE_PUBLIC_READ = "public-read";
    public static final String X_AMZ_ACL_HEADER_VALUE_PRIVATE = "private";

    /**
     * Uploads file with public read access. Alias for {@link #uploadPublicFile(URL, File)}
     *
     * @param url         upload url.
     * @param contentType content type.
     * @param file        file for upload.
     */
    public static void uploadFile(final URL url, final String contentType, final File file) throws IOException {
        uploadPublicFile(url, contentType, file);
    }

    /**
     * Uploads file with public read access.
     *
     * @param url         upload url.
     * @param contentType content type.
     * @param file        file for upload.
     */
    public static void uploadPublicFile(final URL url, final String contentType, final File file)
            throws IOException {

        HttpURLConnection connection = getConnectionForPublicUpload(url, contentType);
        try (OutputStream output = connection.getOutputStream();
                WritableByteChannel wbc = Channels.newChannel(output);
                FileInputStream fis = new FileInputStream(file);
                FileChannel fc = fis.getChannel()) {
            fc.transferTo(0, fc.size(), wbc);
        }
        validateConnectionAfterUpload(connection);
    }

    /**
     * Uploads file with public read access. Will try to determine content type.
     *
     * @param url  upload url.
     * @param file file for upload.
     */
    public static void uploadPublicFile(final URL url, final File file) throws IOException {

        String contentType = URLConnection.guessContentTypeFromName(file.getName());
        uploadPublicFile(url, contentType, file);
    }

    /**
     * Uploads text as a file content with public read access. Alias for {@link #uploadPublicContent(URL, String, String)}
     *
     * @param url         upload url.
     * @param contentType content type.
     * @param content     text content.
     */
    public static void uploadContent(final URL url, final String contentType, final String content)
            throws IOException {
        uploadPublicContent(url, contentType, content);
    }

    /**
     * Uploads text as a file content with public read access.
     *
     * @param url         upload url.
     * @param contentType content type.
     * @param content     text content.
     */
    public static void uploadPublicContent(final URL url, final String contentType, final String content)
            throws IOException {

        HttpURLConnection connection = getConnectionForPublicUpload(url, contentType);
        try (OutputStream output = connection.getOutputStream();
                BufferedOutputStream bos = new BufferedOutputStream(output)) {
            bos.write(content.getBytes());
        }
        validateConnectionAfterUpload(connection);
    }

    /**
     * Uploads text as a file content with PRIVATE read access.
     *
     * @param uri upload {@link URI}
     * @param contentTypeString content type
     * @param contentString text content
     * @throws IOException
     */
    public static void uploadPrivateContent(final URI uri, final String contentTypeString,
            final String contentString) throws IOException {

        LOGGER.info("uploadPrivateContent START: uri: [{}]; content type: [{}], content length: [{}]",
                new Object[] { uri, contentTypeString, contentString.length() });

        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();

        HttpPut httpPut = new HttpPut(uri);
        httpPut.addHeader(HttpHeaders.CONTENT_TYPE, contentTypeString);
        httpPut.addHeader(FileUtils.X_AMZ_ACL_HEADER_NAME, FileUtils.X_AMZ_ACL_HEADER_VALUE_PRIVATE);

        ContentType contentType = ContentType.create(contentTypeString);
        StringEntity stringEntity = new StringEntity(contentString, contentType);

        httpPut.setEntity(stringEntity);

        CloseableHttpResponse response = closeableHttpClient.execute(httpPut);
        StatusLine statusLine = response.getStatusLine();

        if (!(statusLine.getStatusCode() == HttpStatus.SC_OK)) {
            throw new IOException(String.format("An error occurred while trying to upload private file - %d: %s",
                    statusLine.getStatusCode(), statusLine.getReasonPhrase()));
        }

        LOGGER.info("uploadPrivateContent END: uri: [{}]; content type: [{}], content length: [{}]",
                new Object[] { uri, contentTypeString, contentString.length() });
    }

    /**
     * Uploads a {@code File} with PRIVATE read access.
     *
     * @param uri upload {@link URI}
     * @param contentTypeString content type
     * @param contentFile the file to upload
     * @throws IOException
     */
    public static void uploadPrivateContent(final URI uri, final String contentTypeString, final File contentFile)
            throws IOException {

        LOGGER.info("uploadPrivateContent START: uri: [{}]; content type: [{}], content file: [{}]",
                new Object[] { uri, contentTypeString, contentFile });

        CloseableHttpClient closeableHttpClient = HttpClients.createDefault();

        HttpPut httpPut = new HttpPut(uri);
        httpPut.addHeader(HttpHeaders.CONTENT_TYPE, contentTypeString);
        httpPut.addHeader(FileUtils.X_AMZ_ACL_HEADER_NAME, FileUtils.X_AMZ_ACL_HEADER_VALUE_PRIVATE);

        ContentType contentType = ContentType.create(contentTypeString);
        FileEntity fileEntity = new FileEntity(contentFile, contentType);
        httpPut.setEntity(fileEntity);

        CloseableHttpResponse response = closeableHttpClient.execute(httpPut);
        StatusLine statusLine = response.getStatusLine();

        if (!(statusLine.getStatusCode() == HttpStatus.SC_OK)) {
            throw new IOException(String.format("An error occurred while trying to upload private file - %d: %s",
                    statusLine.getStatusCode(), statusLine.getReasonPhrase()));
        }

        LOGGER.info("uploadPrivateContent END: uri: [{}]; content type: [{}], content file: [{}]",
                new Object[] { uri, contentTypeString, contentFile });
    }

    /**
     * Reads from {@link InputStream} provided and uploads data to Cloud as a file with public read access.
     *
     * Alias for {@link #uploadPublicStream(URL, String, InputStream)}
     *
     * @param url         upload url.
     * @param contentType content type.
     * @param stream      {@link InputStream} where to read from. Should be closed externally.
     */
    public static void uploadStream(final URL url, final String contentType, final InputStream stream)
            throws IOException {
        uploadPublicStream(url, contentType, stream);
    }

    /**
     * Reads from {@link InputStream} provided and uploads data to Cloud as a file with public read access.
     *
     * @param url         upload url.
     * @param contentType content type.
     * @param stream      {@link InputStream} where to read from. Should be closed externally.
     */
    public static void uploadPublicStream(final URL url, final String contentType, final InputStream stream)
            throws IOException {

        HttpURLConnection connection = getConnectionForPublicUpload(url, contentType);
        try (OutputStream output = connection.getOutputStream()) {
            IOUtils.copy(stream, output);
        }
        validateConnectionAfterUpload(connection);
    }

    private static HttpURLConnection getConnectionForPublicUpload(final URL url, final String contentType)
            throws IOException {

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod(HttpPut.METHOD_NAME);
        connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, contentType);
        connection.setRequestProperty(X_AMZ_ACL_HEADER_NAME, X_AMZ_ACL_HEADER_VALUE_PUBLIC_READ);
        connection.setDoOutput(true);
        connection.connect();
        return connection;
    }

    private static HttpURLConnection getConnectionForPrivateUpload(final URL url, final String contentType)
            throws IOException {

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod(HttpPut.METHOD_NAME);

        connection.setRequestProperty(HttpHeaders.CONTENT_TYPE, contentType);
        connection.setRequestProperty(X_AMZ_ACL_HEADER_NAME, X_AMZ_ACL_HEADER_VALUE_PRIVATE);
        connection.setDoOutput(true);
        connection.connect();
        return connection;
    }

    private static void validateConnectionAfterUpload(final HttpURLConnection connection) throws IOException {

        int responseCode = connection.getResponseCode();
        if (responseCode == 200) {
            try (final InputStream is = connection.getInputStream()) {
                while (is.read() > 0) {
                    // consume
                }
            }
        } else {
            try (final InputStream is = connection.getErrorStream()) {
                final String error = IOUtils.toString(is);
                throw new IOException(String.format("Unable to upload file. Got error %d %s: %s", responseCode,
                        connection.getResponseMessage(), error));
            }
        }
        connection.disconnect();
    }
}