Example of uploading a file: + * + *
{@code
+ * String bucketName = "my-unique-bucket";
+ * String fileName = "readme.txt";
+ * BlobId blobId = BlobId.of(bucketName, fileName);
+ * BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType("text/plain").build();
+ * storage.createFrom(blobInfo, Paths.get(fileName));
+ * }
+ *
+ * @param blobInfo blob to create
+ * @param path file to upload
+ * @param options blob write options
+ * @return a {@code Blob} with complete information
+ * @throws IOException on I/O error
+ * @throws StorageException on server side error
+ * @see #createFrom(BlobInfo, Path, int, BlobWriteOption...)
+ */
+ Blob createFrom(BlobInfo blobInfo, Path path, BlobWriteOption... options) throws IOException;
+
+ /**
+ * Uploads {@code path} to the blob using {@link #writer} and {@code bufferSize}. By default any
+ * MD5 and CRC32C values in the given {@code blobInfo} are ignored unless requested via the {@link
+ * BlobWriteOption#md5Match()} and {@link BlobWriteOption#crc32cMatch()} options. Folder upload is
+ * not supported.
+ *
+ * {@link #createFrom(BlobInfo, Path, BlobWriteOption...)} invokes this method with a buffer + * size of 15 MiB. Users can pass alternative values. Larger buffer sizes might improve the upload + * performance but require more memory. This can cause an OutOfMemoryError or add significant + * garbage collection overhead. Smaller buffer sizes reduce memory consumption, that is noticeable + * when uploading many objects in parallel. Buffer sizes less than 256 KiB are treated as 256 KiB. + * + *
Example of uploading a humongous file: + * + *
{@code
+ * BlobId blobId = BlobId.of(bucketName, blobName);
+ * BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType("video/webm").build();
+ *
+ * int largeBufferSize = 150 * 1024 * 1024;
+ * Path file = Paths.get("humongous.file");
+ * storage.createFrom(blobInfo, file, largeBufferSize);
+ * }
+ *
+ * @param blobInfo blob to create
+ * @param path file to upload
+ * @param bufferSize size of the buffer I/O operations
+ * @param options blob write options
+ * @return a {@code Blob} with complete information
+ * @throws IOException on I/O error
+ * @throws StorageException on server side error
+ */
+ Blob createFrom(BlobInfo blobInfo, Path path, int bufferSize, BlobWriteOption... options)
+ throws IOException;
+
+ /**
+ * Reads bytes from an input stream and uploads those bytes to the blob using {@link #writer}. By
+ * default any MD5 and CRC32C values in the given {@code blobInfo} are ignored unless requested
+ * via the {@link BlobWriteOption#md5Match()} and {@link BlobWriteOption#crc32cMatch()} options.
+ *
+ * Example of uploading data with CRC32C checksum: + * + *
{@code
+ * BlobId blobId = BlobId.of(bucketName, blobName);
+ * byte[] content = "Hello, world".getBytes(StandardCharsets.UTF_8);
+ * Hasher hasher = Hashing.crc32c().newHasher().putBytes(content);
+ * String crc32c = BaseEncoding.base64().encode(Ints.toByteArray(hasher.hash().asInt()));
+ * BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setCrc32c(crc32c).build();
+ * storage.createFrom(blobInfo, new ByteArrayInputStream(content), Storage.BlobWriteOption.crc32cMatch());
+ * }
+ *
+ * @param blobInfo blob to create
+ * @param content input stream to read from
+ * @param options blob write options
+ * @return a {@code Blob} with complete information
+ * @throws IOException on I/O error
+ * @throws StorageException on server side error
+ * @see #createFrom(BlobInfo, InputStream, int, BlobWriteOption...)
+ */
+ Blob createFrom(BlobInfo blobInfo, InputStream content, BlobWriteOption... options)
+ throws IOException;
+
+ /**
+ * Reads bytes from an input stream and uploads those bytes to the blob using {@link #writer} and
+ * {@code bufferSize}. By default any MD5 and CRC32C values in the given {@code blobInfo} are
+ * ignored unless requested via the {@link BlobWriteOption#md5Match()} and {@link
+ * BlobWriteOption#crc32cMatch()} options.
+ *
+ * {@link #createFrom(BlobInfo, InputStream, BlobWriteOption...)} )} invokes this method with a
+ * buffer size of 15 MiB. Users can pass alternative values. Larger buffer sizes might improve the
+ * upload performance but require more memory. This can cause an OutOfMemoryError or add
+ * significant garbage collection overhead. Smaller buffer sizes reduce memory consumption, that
+ * is noticeable when uploading many objects in parallel. Buffer sizes less than 256 KiB are
+ * treated as 256 KiB.
+ *
+ * @param blobInfo blob to create
+ * @param content input stream to read from
+ * @param bufferSize size of the buffer I/O operations
+ * @param options blob write options
+ * @return a {@code Blob} with complete information
+ * @throws IOException on I/O error
+ * @throws StorageException on server side error
+ */
+ Blob createFrom(
+ BlobInfo blobInfo, InputStream content, int bufferSize, BlobWriteOption... options)
+ throws IOException;
+
/**
* Returns the requested bucket or {@code null} if not found.
*
diff --git a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java
index 0e24521eb6..b1f2bfe3c3 100644
--- a/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java
+++ b/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java
@@ -48,6 +48,7 @@
import com.google.cloud.ReadChannel;
import com.google.cloud.RetryHelper.RetryHelperException;
import com.google.cloud.Tuple;
+import com.google.cloud.WriteChannel;
import com.google.cloud.storage.Acl.Entity;
import com.google.cloud.storage.HmacKey.HmacKeyMetadata;
import com.google.cloud.storage.PostPolicyV4.ConditionV4Type;
@@ -70,12 +71,18 @@
import com.google.common.io.BaseEncoding;
import com.google.common.primitives.Ints;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
@@ -99,6 +106,9 @@ final class StorageImpl extends BaseService