yandisk4j
is a lightweight Java 17 wrapper for the Yandex Disk cloud storage API.
This is a modernization of yandex-disk-restapi-java with
less dependencies, better documentation and better syntax.
dependencies {
implementation("io.github.wasabithumb:yandisk4j:0.4.0")
}
dependencies {
implementation 'io.github.wasabithumb:yandisk4j:0.4.0'
}
<dependency>
<groupId>io.github.wasabithumb</groupId>
<artifactId>yandisk4j</artifactId>
<version>0.4.0</version>
<scope>compile</scope>
</dependency>
The Yandex Disk API is OAuth authenticated, which means it requires a unique OAuth token for each combination of
application & user account. yandisk4j
includes a helper for generating OAuth tokens. If you have your own method,
feel free to skip to Entry.
Using the auth helper requires having an application with a client ID, client secret, and
permission to use the cloud_api:disk.*
scopes.
// CODE : Retrieve the authorization code from a redirect URL you control
// SCREEN_CODE : Retrieve the authorization code from the end user
// LOCAL_CODE : Automatically retrieve the authorization code from a temporary local HTTP server
final AuthHandler auth = YanDisk.auth(AuthScheme.SCREEN_CODE)
.clientID("YOUR_CLIENT_ID_HERE")
.clientSecret("YOUR_CLIENT_SECRET_HERE")
.scopes(AuthScope.INFO, AuthScope.READ /* etc */)
.build();
// Open URL in the system browser
auth.openURL();
String code;
// CODE : ¯\_(ツ)_/¯
// SCREEN_CODE : code = promptUserForAuthCode();
// LOCAL_CODE : code = auth.awaitCode().code();
AuthResponse response = auth.exchange(code);
System.out.println("OAuth token: " + response.accessToken());
The default redirect URL for LOCAL_CODE
is http://127.0.0.1:8127/
. Make sure to add this to your application
or specify a local redirect URL you control when building the AuthHandler
.
The default HTTP server is com.sun.net.httpserver.HttpServer
.
Due to the nature of com.sun.*
packages, it's not a guarantee that your JRE will have it (though as of writing,
Oracle & OpenJDK both do). If this behavior is not acceptable, you can use
NanoHTTPD as a fallback provider.
Example with Gradle:
implementation("io.github.wasabithumb:yandisk4j:0.2.1") {
capabilities {
requireCapability("io.github.wasabithumb:yandisk4j-nanohttpd")
}
}
To create a new YanDisk
instance:
YanDisk yd = YanDisk.yanDisk(oauthToken);
To create a YanDisk
instance with a dynamic (refreshing) OAuth token:
YanDisk yd = YanDisk.yanDisk(() -> {
// Return your OAuth token here
});
YanDisk yd = YanDisk.yanDisk(/* ... */);
for (Node n : yd.listAll()) {
System.out.println("- " + n.path());
}
YanDisk yd = YanDisk.yanDisk(/* ... */);
for (Node n : yd.list("disk:/path/to/dir")) {
if (n.isDirectory())
System.out.println("D > " + n.name());
if (n.isFile())
System.out.println("F > " + n.name());
}
Multiple methods are shown below, choose only 1
YanDisk yd = YanDisk.yanDisk(/* ... */);
NodeUploader nu = yd.upload("disk:/remote/path/to/file.bin");
File file = new File("local/path/to/file.bin");
// Sync
nu.write(file);
// Sync (stream)
nu.write(new FileInputStream(file));
// Sync (stream)
try (InputStream is = new FileInputStream(file);
OutputStream os = nu.write()
) {
// Pipe "is" to "os"
}
// Async
Transfer t = nu.writeAsync(file);
// Async (stream)
Transfer t = nu.writeAsync(new FileInputStream(file), file.length());
See Working with Transfers for more info.
Multiple methods are shown below, choose only 1
YanDisk yd = YanDisk.yanDisk(/* ... */);
NodeDownloader nd = yd.download("disk:/remote/path/to/file.bin");
File file = new File("local/path/to/file.bin");
// Sync
nd.read(file);
// Sync (stream)
try (InputStream is = nd.open();
OutputStream os = new FileOutputStream(file)
) {
// Pipe "is" to "os"
}
// Async
Transfer t = nd.readAsync(file);
// Async (stream)
Transfer t = nd.readAsync(new FileOutputStream(file));
See Working with Transfers for more info.
YanDisk yd = YanDisk.yanDisk(/* ... */);
Operation op = yd.copy("disk:/a.txt", "disk:/b.txt");
See Working with Operations for more info.
YanDisk yd = YanDisk.yanDisk(/* ... */);
Operation op = yd.move("disk:/a.txt", "disk:/b.txt");
See Working with Operations for more info.
YanDisk yd = YanDisk.yanDisk(/* ... */);
Operation op = yd.delete("disk:/stuff");
See Working with Operations for more info.
YanDisk yd = YanDisk.yanDisk(/* ... */);
yd.mkdir("disk:/path/to/dir");
// This is not recursive! In this case, disk:/path/to must already exist.
Watchable
defines the common methods of Operation and Transfer.
In other words, it is similar to a CompletableFuture.
Their differences are outlined further below.
Watchable<?> w = /* ... */;
w.watch((Watchable<?> ignored) -> {
// Watchable has changed
if (w.hasProgress()) {
double progress = w.progress();
}
if (w.isDone()) {
// Done
}
});
A few large operations (copy, move, delete)
may return an Operation
. An Operation is an asynchronous OperationStatus
accessor that can be queried with
status()
and listened to with watch(Consumer<Operation>)
. For example:
Operation op = /* ... */;
op.setRefreshInterval(200L); // Refresh every 200ms
// Operation daemon does not start until "status" or "watch" are called. At this point, no requests are scheduled.
op.watch((Operation ignored) -> {
System.out.println(op.status()); // PENDING, SUCCESS or FAILED
});
A Transfer
can be created using the async methods on NodeUploader
/NodeDownloader
. The job of a Transfer
is to monitor a pipe and provide thread-safe access to the pipe's completion state and progress (if possible).
Transfer t = /* ... */;
t.block(); // Wait for transfer to complete (isDone() becomes true)
if (t.error() != null) {
// Broken pipe
}
Transfer
is a Watchable and can be listened for changes with watch(Consumer<Transfer>)
.
Copyright 2024 Wasabi Codes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.