@Override public Void call() throws Exception { InputStream is = s3Client.readObjectStream(bucket, key, range); try { is = new ProgressInputStream(is, LargeFileDownloader.this); byte[] buffer = new byte[32 * 1024]; long pos = range.getFirst(); for (int r = 0; r != -1; r = is.read(buffer)) { channel.write(ByteBuffer.wrap(buffer, 0, r), pos); pos += r; } return null; } finally { try { is.close(); } catch (Throwable t) { log.warn("could not close object stream", t); } } } }
@Override public InputStream readObjectStream(String bucketName, String key, Range range) { byte[] bytes = new byte[Math.toIntExact(range.getLast() + 1 - range.getFirst())]; Path path = Paths.get(this.baseDir, bucketName, key); FileInputStream returnStream; try { returnStream = new FileInputStream(path.toFile()); if (range.getFirst() != 0) { long bytesSkipped = 0; do { bytesSkipped += returnStream.skip(range.getFirst()); } while (bytesSkipped < range.getFirst()); } StreamHelpers.readAll(returnStream, bytes, 0, bytes.length); return new ByteArrayInputStream(bytes); } catch (IOException e) { throw new S3Exception("NoSuchKey", HttpStatus.SC_NOT_FOUND, "NoSuchKey", ""); } }
@Synchronized @Override public void putObject(String bucketName, String key, Range range, Object content) { Path path = Paths.get(this.baseDir, bucketName, key); try (FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE)) { long startOffset = range.getFirst(); long length = range.getLast() + 1 - range.getFirst(); do { long bytesTransferred = channel.transferFrom(Channels.newChannel((InputStream) content), range.getFirst(), range.getLast() + 1 - range.getFirst()); length -= bytesTransferred; startOffset += bytesTransferred; } while (length > 0); AclSize aclKey = aclMap.get(key); aclMap.put(key, aclKey.withSize(range.getLast() + 1)); } catch (IOException e) { throw new S3Exception("NoObject", 404, "NoSuchKey", key); } }
@Synchronized @Override public void putObject(String bucketName, String key, Range range, Object content) { byte[] totalByes = new byte[Math.toIntExact(range.getLast() + 1)]; try { if (range.getFirst() != 0) { int bytesRead = client.getObject(bucketName, key).getObject().read(totalByes, 0, Math.toIntExact(range.getFirst())); if (bytesRead != range.getFirst()) { throw new IllegalStateException("Unable to read from the object " + key); } } int bytesRead = ((InputStream) content).read(totalByes, Math.toIntExact(range.getFirst()), Math.toIntExact(range.getLast() + 1 - range.getFirst())); if (bytesRead != range.getLast() + 1 - range.getFirst()) { throw new IllegalStateException("Not able to read from input stream."); } client.putObject(new PutObjectRequest(bucketName, key, (Object) new ByteArrayInputStream(totalByes))); aclMap.put(key, aclMap.get(key).withSize(range.getLast() - 1)); } catch (IOException e) { throw new S3Exception("NoObject", HttpStatus.SC_NOT_FOUND, "NoSuchKey", key); } }
@Synchronized @Override public CompleteMultipartUploadResult completeMultipartUpload(CompleteMultipartUploadRequest request) { Map<Integer, CopyPartRequest> partMap = multipartUploads.get(request.getKey()); if (partMap == null) { throw new S3Exception("NoSuchKey", HttpStatus.SC_NOT_FOUND, "NoSuchKey", ""); } try { partMap.forEach((index, copyPart) -> { if (!copyPart.getKey().equals(copyPart.getSourceKey())) { Path sourcePath = Paths.get(this.baseDir, copyPart.getBucketName(), copyPart.getSourceKey()); Path targetPath = Paths.get(this.baseDir, copyPart.getBucketName(), copyPart.getKey()); try (FileChannel sourceChannel = FileChannel.open(sourcePath, StandardOpenOption.READ); FileChannel targetChannel = FileChannel.open(targetPath, StandardOpenOption.WRITE)) { targetChannel.transferFrom(sourceChannel, Files.size(targetPath), copyPart.getSourceRange().getLast() + 1 - copyPart.getSourceRange().getFirst()); targetChannel.close(); AclSize aclMap = this.aclMap.get(copyPart.getKey()); this.aclMap.put(copyPart.getKey(), aclMap.withSize(Files.size(targetPath))); } catch (IOException e) { throw new S3Exception("NoSuchKey", 404, "NoSuchKey", ""); } } }); } finally { multipartUploads.remove(request.getKey()); } return new CompleteMultipartUploadResult(); }