-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathStreamTransfer.class.php
More file actions
executable file
·95 lines (88 loc) · 2.19 KB
/
StreamTransfer.class.php
File metadata and controls
executable file
·95 lines (88 loc) · 2.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?php namespace io\streams;
use io\IOException;
use lang\Closeable;
/**
* A stream transfer copies from an input stream to an output stream
*
* Example (downloading a file):
* ```php
* $t= new StreamTransfer(
* (new HttpConnection('http://example.com'))->get('/')->getInputStream(),
* new FileOutputStream(new File('index.html'))
* );
* $t->transferAll();
* $t->close();
* ```
*
* @test io.unittest.StreamTransferTest
*/
class StreamTransfer implements Closeable {
protected $in, $out;
/**
* Creates a new stream transfer
*
* @param io.streams.InputStream $in
* @param io.streams.OutputStream $out
*/
public function __construct(InputStream $in, OutputStream $out) {
$this->in= $in;
$this->out= $out;
}
/**
* Copy all available input from in
*
* @return int number of bytes copied
* @throws io.IOException
*/
public function transferAll() {
$r= 0;
while ($this->in->available()) {
$chunk= $this->in->read();
$this->out->write($chunk);
$r+= strlen($chunk);
}
return $r;
}
/**
* Transmit all available input from in, yielding control after each chunk.
* Uses default chunk size of 8192 bytes.
*
* @param int $size
* @return iterable
* @throws io.IOException
*/
public function transmit($size= 8192) {
while ($this->in->available()) {
$chunk= $this->in->read($size);
$this->out->write($chunk);
yield strlen($chunk);
}
}
/**
* Close input and output streams. Guarantees to try to close both
* streams even if one of the close() calls yields an exception.
*
* @return void
* @throws io.IOException
*/
public function close() {
$errors= '';
try {
$this->in->close();
} catch (IOException $e) {
$errors.= ', Could not close input stream: '.$e->getMessage();
}
try {
$this->out->close();
} catch (IOException $e) {
$errors.= ', Could not close output stream: '.$e->getMessage();
}
if ($errors) {
throw new IOException(substr($errors, 2));
}
}
/** @return string */
public function toString() {
return nameof($this).'('.$this->in->toString().' -> '.$this->out->toString().')';
}
}