Proyectos de Subversion Moodle

Rev

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