java - 复制(通过 Web API)完成;不管怎样,我的 pipe 坏了。怎么解决呢?

标签 java box-api broken-pipe

对于one of my projects ,我通过 Box API Java SDK( new one )实现了 Java 7 FileSystem

但是,对于下载文件,当您想要获取内容的流时,它仅提供以 OutputStream 作为参数的方法;具体来说,我正在使用 this one目前。

但这与 JDK API 不太相符;我需要能够实现 FileSystemProvider#newInputStream() ...因此我选择使用Pipe{Input,Output}Stream

此外,由于 Box SDK API 方法是同步的(这在这里并不重要),因此我将它们包装在 Future 中。我的代码如下(为简洁起见省略了导入):

@ParametersAreNonnullByDefault
public final class BoxFileInputStream
    extends InputStream
{
    private final Future<Void> future;
    private final PipedInputStream in;

    public BoxFileInputStream(final ExecutorService executor,
        final BoxFile file)
    {
        in = new PipedInputStream(16384);
        future = executor.submit(new Callable<Void>()
        {
            @Override
            public Void call()
                throws IOException
            {
                try {
                    file.download(new PipedOutputStream(in));
                    return null;
                } catch (BoxAPIException e) {
                    throw BoxIOException.wrap(e);
                }
            }
        });
    }

    @Override
    public int read()
        throws IOException
    {
        try {
            return in.read();
        } catch (IOException e) {
            future.cancel(true);
            throw new BoxIOException("download failure", e);
        }
    }

    @Override
    public int read(final byte[] b)
        throws IOException
    {
        try {
            return in.read(b);
        } catch (IOException e) {
            future.cancel(true);
            throw new BoxIOException("download failure", e);
        }
    }

    @Override
    public int read(final byte[] b, final int off, final int len)
        throws IOException
    {
        try {
            return in.read(b, off, len);
        } catch (IOException e) {
            future.cancel(true);
            throw new BoxIOException("download failure", e);
        }
    }

    @Override
    public long skip(final long n)
        throws IOException
    {
        try {
            return in.skip(n);
        } catch (IOException e) {
            future.cancel(true);
            throw new BoxIOException("download failure", e);
        }
    }

    @Override
    public int available()
        throws IOException
    {
        try {
            return in.available();
        } catch (IOException e) {
            future.cancel(true);
            throw new BoxIOException("download failure", e);
        }
    }

    @Override
    public void close()
        throws IOException
    {
        IOException streamException = null;
        IOException futureException = null;

        try {
            in.close();
        } catch (IOException e) {
            streamException = e;
        }

        try {
            future.get(5L, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            futureException = new BoxIOException("donwload interrupted", e);
        } catch (ExecutionException e) {
            futureException = new BoxIOException("download failure",
                e.getCause());
        } catch (CancellationException e) {
            futureException = new BoxIOException("download cancelled", e);
        } catch (TimeoutException e) {
            futureException = new BoxIOException("download timeout", e);
        }

        if (futureException != null) {
            if (streamException != null)
                futureException.addSuppressed(streamException);
            throw futureException;
        }

        if (streamException != null)
            throw streamException;
    }

    @Override
    public synchronized void mark(final int readlimit)
    {
        in.mark(readlimit);
    }

    @Override
    public synchronized void reset()
        throws IOException
    {
        try {
            in.reset();
        } catch (IOException e) {
            future.cancel(true);
            throw new BoxIOException("download failure", e);
        }
    }

    @Override
    public boolean markSupported()
    {
        return in.markSupported();
    }
}

代码始终失败,并显示以下堆栈跟踪(位于 int read(byte[]) 中:

Exception in thread "main" com.github.fge.filesystem.box.exceptions.BoxIOException: download failure
    at com.github.fge.filesystem.box.io.BoxFileInputStream.read(BoxFileInputStream.java:81)
    at java.nio.file.Files.copy(Files.java:2735)
    at java.nio.file.Files.copy(Files.java:2854)
    at java.nio.file.CopyMoveHelper.copyToForeignTarget(CopyMoveHelper.java:126)
    at java.nio.file.Files.copy(Files.java:1230)
    at Main.main(Main.java:37)
    [ IDEA specific stack trace elements follow -- irrelevant]
Caused by: java.io.IOException: Pipe broken
    at java.io.PipedInputStream.read(PipedInputStream.java:322)
    at java.io.PipedInputStream.read(PipedInputStream.java:378)
    at java.io.InputStream.read(InputStream.java:101)
    at com.github.fge.filesystem.box.io.BoxFileInputStream.read(BoxFileInputStream.java:78)
    ... 10 more

但是当失败时,下载已经完成了...

好吧,问题是,我可以获取文件大小并对其进行破解,但如果可能的话我宁愿不这样做;如何修改此代码以避免 EPIPE?

最佳答案

SDK还提供BoxAPIRequestBoxAPIResponse允许您手动请求高级用例的类。这些类仍然自动处理身份验证、错误、回退等,但使您可以更精细地控制请求。

就你而言,你可以做一个 download request手动执行以下操作:

// Note: this example assumes you already have a BoxAPIConnection.
URL url = new URL("files/" + file.getID() + "/content")
BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
BoxAPIResponse response = request.send();

InputStream bodyStream = response.getBody();
// Use the stream.
response.disconnect();

关于java - 复制(通过 Web API)完成;不管怎样,我的 pipe 坏了。怎么解决呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27454899/

相关文章:

java - 对字符串执行的最小循环(向前或向后)移位以使其成为回文

go - 使用 Go to the box 帐户上传文件和文件夹

linux - 为什么我很少而不是总是得到 "cat: write error: Broken pipe"

java - LOG4J与JBOSS&Java程序冲突

java - 多次执行 Android 方法时出现 Broken pipe 错误?

java - 将可能为 null 的 Integer 与常量进行比较时,是否可以避免进行 null 检查?

Java 日期时间查看

java - 使 JLabel 适合其父 JPanel 或为其指定最小尺寸

android - 如何将重定向 URI 与 OAuth2.0 和 Box 一起用于我的 Android 应用程序?

box-api - OpenSSL 无法验证数据 : error:0906D06C:PEM routines:PEM_read_bio:no start line in Box API