当前位置: 首页 > 知识库问答 >
问题:

如何使用OKIO正确地读取一个文件块?

巫马泰
2023-03-14

不管怎样,我在我的项目中使用了registfit/OkHttp,并认为这应该是Okio的一个很好的用法。这就是我目前所拥有的,它似乎起作用了。但是我是Okio的新手,不知道我是否遗漏了一些明显的东西,或者这是否可以用更好的方式来完成。

private void chunkedUpload(int offset, int chunkSize, int blockNumber, @Nonnull CompletableFuture<Foo> future) {
  File file = ...
  String url = ...

  try (final BufferedSource bufferedSource = Okio.buffer(Okio.source(file))) {
    bufferedSource.skip(offset);
    final Buffer buffer = new Buffer();
    final boolean isFinal = !bufferedSource.request(chunkSize);
    bufferedSource.read(buffer, chunkSize);
    final RequestBody requestFile = RequestBody.create(buffer.readByteArray(), null);
    upload(offset, chunkSize, url, requestFile, blockNumber, future, isFinal);
  } catch (IOException e) {
    future.completeExceptionally(e);
  }
}

private void upload(int offset, int chunkSize, @Nonnull String url, @Nonnull RequestBody requestFile, int blockNumber, @Nonnull CompletableFuture<Foo> future, boolean isFinal) {
        fileUloadService.uploadApp(url + "&block_number=" + blockNumber, requestFile)
            .whenComplete((responseBody, throwable) -> {
                if (throwable != null) {
                    future.completeExceptionally(throwable);
                } else {
                    if (isFinal) {
                        future.complete();
                        return;
                    }

                    chunkedUpload(offset + chunkSize, chunkSize, blockNumber + 1, future);
                }
            });
    }

您可以看到,我正在绑定upload一个块,等待成功响应(来自Java8CompletableFuture),然后使用更新的OffsetBlockNumber再次调用ChunkedUpload方法。就像我说的,它很有效,但我是Okio的新手,我想知道我是否错过了一些明显的东西?

我想使用Okio的原因很大程度上是因为我要上传的文件通常在30MB到1GB之间,所以不要想一下子把所有这些都加载到内存中:)。

共有1个答案

闻人宝
2023-03-14

这是我使用Okio和OkHttp从assets文件夹读取图像文件并将其作为多部分/表单数据发送到请求正文中的代码。

您基本需要:

  1. 创建OKHttpClient
  2. 创建RequestBody对象
  3. 将RequestBody添加为多部分/表单数据
  4. 创建一个Request对象,将RequestBody和头添加到该对象中
  5. 使用OkHttpClient调用请求
  6. 向队列中添加回调,以便您可以返回响应bject
    // Read image file from the assets folder
    BufferedSource img = Okio.buffer(Okio.source(getAssets().open("image.jpg")));
    byte[] image = img.readByteArray();

    // Create the OkHttpClient
    OkHttpClient client = new OkHttpClient().newBuilder().build();

    // Create the request body
    RequestBody rq =  RequestBody.create(MediaType.parse("image/jpeg"),image);

    RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
            .addFormDataPart("image", "image.jpg", rq)
            .build();

    // Create the request and add the RequestBody to it
    Request request = new Request.Builder()
            .url(YOUR_URL)
            .method("POST", body)
            .addHeader("Authorization", "Bearer " + BEARER_TOKEN)
            .build();

    // Use OkHttpClient to call the request
    client.newCall(request).enqueue(new okhttp3.Callback() {
        @Override
        public void onFailure(okhttp3.Call call, IOException e) {
            Snackbar.make(upload, "Error", Snackbar.LENGTH_SHORT).show();

        }

        @Override
        public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
            Snackbar.make(upload, "Success", Snackbar.LENGTH_SHORT).show();

        }
    });
 类似资料:
  • 问题内容: 我无法弄清楚/的运作方式。我对此有些了解,但无法使其正常工作。 我知道我可以使用,但是如果这样做,我知道我永远不会理解/ 我只会埋葬这个问题。 目标:调用并返回文件的内容。 每次调用该文件都会增加一次(每页加载)。该文件包含二进制缓冲区的转储,并存储在SSD中。 无论我做什么,都会出现错误或在控制台中。 问题答案: 要使用/,您需要返回承诺的方法。没有包装器,核心API函数就不会这样做

  • 我想以UTF-8快速地逐行读取大的csv文件(大约~1GB)。我已经为它创建了一个类,但它不能正常工作。UTF-8从2字节解码西里尔符号。我使用字节缓冲区来读取它,例如,它有10个字节的长度。因此,如果文件中的符号由10和11字节组成,它将无法正常解码:(

  • 我发现其他人也有同样的问题,他们的问题通过在InputStreamReader构造函数中指定UTF-8来解决: 以UTF-8形式读取InputStream 这对我不起作用,我也不知道为什么。无论我尝试什么,我总是得到转义的unicode值(斜杠-U+十六进制),而不是实际的语言字符。我在这里做错了什么?提前道谢! 请注意:这不是字体问题。我之所以知道这一点,是因为如果我对同一个文件使用Resour

  • 我试图通过创建一个函数来编写一个简单的文本文件阅读器,该函数接受文件的路径并将每行文本转换为char数组,但它不起作用。 这里出了什么问题? 从以前的修订版更改了一点代码后,这似乎仍然不起作用,现在它给我一个异常101。 我在Firefox上测试过这个功能,它可以工作,但在Google Chrome上它就是不工作,它一直给我一个异常101。我如何让它不仅适用于Firefox,还适用于其他浏览器(尤

  • 我使用AWS lambda作为后端来解析最近上传的文件,并维护一个json“peak”文件。我遇到的问题是,当用户上载多个文件时,同时调用lambda函数来维护峰值文件。因此,它在不等待前一个实例执行的情况下读取“peak”文件,结果是只有约1/3的文件被写入peak文件。 不幸的是,我不能批量上传到s3,也不能使用多部分上传,因为在应用程序的其余部分中,我需要每个单独的文件都在s3中自己的密钥下

  • 我有以下代码来读取java文件,并打印出行。我通过两种方式实现了它: 使用流: 使用循环: 我被告知这是错误的,使用缓冲读取器是错误地使用了语言的特性。有没有更好的方法,我想知道使用语言功能的正确方法。