Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\Multipart;
3
 
4
use Aws\AwsClientInterface as Client;
5
use Aws\Exception\AwsException;
6
use GuzzleHttp\Psr7;
7
use InvalidArgumentException as IAE;
8
use Psr\Http\Message\StreamInterface as Stream;
9
 
10
abstract class AbstractUploader extends AbstractUploadManager
11
{
12
    /** @var Stream Source of the data to be uploaded. */
13
    protected $source;
14
 
15
    /**
16
     * @param Client $client
17
     * @param mixed  $source
18
     * @param array  $config
19
     */
20
    public function __construct(Client $client, $source, array $config = [])
21
    {
22
        $this->source = $this->determineSource($source);
23
        parent::__construct($client, $config);
24
    }
25
 
26
    /**
27
     * Create a stream for a part that starts at the current position and
28
     * has a length of the upload part size (or less with the final part).
29
     *
30
     * @param Stream $stream
31
     *
32
     * @return Psr7\LimitStream
33
     */
34
    protected function limitPartStream(Stream $stream)
35
    {
36
        // Limit what is read from the stream to the part size.
37
        return new Psr7\LimitStream(
38
            $stream,
39
            $this->state->getPartSize(),
40
            $this->source->tell()
41
        );
42
    }
43
 
44
    protected function getUploadCommands(callable $resultHandler)
45
    {
46
        // Determine if the source can be seeked.
47
        $seekable = $this->source->isSeekable()
48
            && $this->source->getMetadata('wrapper_type') === 'plainfile';
49
 
50
        for ($partNumber = 1; $this->isEof($seekable); $partNumber++) {
51
            // If we haven't already uploaded this part, yield a new part.
52
            if (!$this->state->hasPartBeenUploaded($partNumber)) {
53
                $partStartPos = $this->source->tell();
54
                if (!($data = $this->createPart($seekable, $partNumber))) {
55
                    break;
56
                }
57
                $command = $this->client->getCommand(
58
                    $this->info['command']['upload'],
59
                    $data + $this->state->getId()
60
                );
61
                $command->getHandlerList()->appendSign($resultHandler, 'mup');
62
                $numberOfParts = $this->getNumberOfParts($this->state->getPartSize());
63
                if (isset($numberOfParts) && $partNumber > $numberOfParts) {
64
                    throw new $this->config['exception_class'](
65
                        $this->state,
66
                        new AwsException(
67
                            "Maximum part number for this job exceeded, file has likely been corrupted." .
68
                            "  Please restart this upload.",
69
                            $command
70
                        )
71
                    );
72
                }
73
 
74
                yield $command;
75
                if ($this->source->tell() > $partStartPos) {
76
                    continue;
77
                }
78
            }
79
 
80
            // Advance the source's offset if not already advanced.
81
            if ($seekable) {
82
                $this->source->seek(min(
83
                    $this->source->tell() + $this->state->getPartSize(),
84
                    $this->source->getSize()
85
                ));
86
            } else {
87
                $this->source->read($this->state->getPartSize());
88
            }
89
        }
90
    }
91
 
92
    /**
93
     * Generates the parameters for an upload part by analyzing a range of the
94
     * source starting from the current offset up to the part size.
95
     *
96
     * @param bool $seekable
97
     * @param int  $number
98
     *
99
     * @return array|null
100
     */
101
    abstract protected function createPart($seekable, $number);
102
 
103
    /**
104
     * Checks if the source is at EOF.
105
     *
106
     * @param bool $seekable
107
     *
108
     * @return bool
109
     */
110
    private function isEof($seekable)
111
    {
112
        return $seekable
113
            ? $this->source->tell() < $this->source->getSize()
114
            : !$this->source->eof();
115
    }
116
 
117
    /**
118
     * Turns the provided source into a stream and stores it.
119
     *
120
     * If a string is provided, it is assumed to be a filename, otherwise, it
121
     * passes the value directly to `Psr7\Utils::streamFor()`.
122
     *
123
     * @param mixed $source
124
     *
125
     * @return Stream
126
     */
127
    private function determineSource($source)
128
    {
129
        // Use the contents of a file as the data source.
130
        if (is_string($source)) {
131
            $source = Psr7\Utils::tryFopen($source, 'r');
132
        }
133
 
134
        // Create a source stream.
135
        $stream = Psr7\Utils::streamFor($source);
136
        if (!$stream->isReadable()) {
137
            throw new IAE('Source stream must be readable.');
138
        }
139
 
140
        return $stream;
141
    }
142
 
143
    protected function getNumberOfParts($partSize)
144
    {
145
        if ($sourceSize = $this->source->getSize()) {
146
            return ceil($sourceSize/$partSize);
147
        }
148
        return null;
149
    }
150
}