aliyun-sdk 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/ext/crcx/crc64_ecma.c +270 -0
- data/ext/crcx/crcx.c +45 -0
- data/ext/crcx/crcx.h +8 -0
- data/ext/crcx/extconf.rb +3 -0
- data/lib/aliyun/oss.rb +1 -0
- data/lib/aliyun/oss/bucket.rb +12 -1
- data/lib/aliyun/oss/client.rb +4 -0
- data/lib/aliyun/oss/config.rb +4 -1
- data/lib/aliyun/oss/download.rb +2 -2
- data/lib/aliyun/oss/exception.rb +6 -0
- data/lib/aliyun/oss/http.rb +9 -4
- data/lib/aliyun/oss/multipart.rb +1 -1
- data/lib/aliyun/oss/protocol.rb +50 -5
- data/lib/aliyun/oss/util.rb +19 -1
- data/lib/aliyun/version.rb +1 -1
- data/spec/aliyun/oss/bucket_spec.rb +54 -0
- data/spec/aliyun/oss/client/bucket_spec.rb +66 -0
- data/spec/aliyun/oss/http_spec.rb +26 -0
- data/spec/aliyun/oss/multipart_spec.rb +45 -0
- data/spec/aliyun/oss/object_spec.rb +153 -0
- data/spec/aliyun/oss/util_spec.rb +50 -0
- data/tests/config.rb +2 -0
- data/tests/helper.rb +15 -0
- data/tests/test_crc_check.rb +184 -0
- data/tests/test_custom_headers.rb +14 -6
- metadata +27 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36daab0f73cf740bf403be9a9dfdec680bf91e13
|
4
|
+
data.tar.gz: efebb230b85672b7785ddc167b186859ff330d83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 690da0dbe97a706c46a67fd5384ab2ec1c7fec65cfab7c5a7b27bc3e9696f4283ee6314eea6ce00f725b60b6a225f091b936cd8e804482ef005c996ec9e85361
|
7
|
+
data.tar.gz: 19bd7510ef836532f657604e1bd12a1e8e404863a8d317c551bdf7c640740344325a7ca12bb52f5f104d370b8c6f3e93efe7cfe163facbc18168b38f57a403eb
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,270 @@
|
|
1
|
+
/* crc64.c -- compute CRC-64
|
2
|
+
* Copyright (C) 2013 Mark Adler
|
3
|
+
* Version 1.4 16 Dec 2013 Mark Adler
|
4
|
+
*/
|
5
|
+
|
6
|
+
/*
|
7
|
+
This software is provided 'as-is', without any express or implied
|
8
|
+
warranty. In no event will the author be held liable for any damages
|
9
|
+
arising from the use of this software.
|
10
|
+
|
11
|
+
Permission is granted to anyone to use this software for any purpose,
|
12
|
+
including commercial applications, and to alter it and redistribute it
|
13
|
+
freely, subject to the following restrictions:
|
14
|
+
|
15
|
+
1. The origin of this software must not be misrepresented; you must not
|
16
|
+
claim that you wrote the original software. If you use this software
|
17
|
+
in a product, an acknowledgment in the product documentation would be
|
18
|
+
appreciated but is not required.
|
19
|
+
2. Altered source versions must be plainly marked as such, and must not be
|
20
|
+
misrepresented as being the original software.
|
21
|
+
3. This notice may not be removed or altered from any source distribution.
|
22
|
+
|
23
|
+
Mark Adler
|
24
|
+
madler@alumni.caltech.edu
|
25
|
+
*/
|
26
|
+
|
27
|
+
/* Compute CRC-64 in the manner of xz, using the ECMA-182 polynomial,
|
28
|
+
bit-reversed, with one's complement pre and post processing. Provide a
|
29
|
+
means to combine separately computed CRC-64's. */
|
30
|
+
|
31
|
+
/* Version history:
|
32
|
+
1.0 13 Dec 2013 First version
|
33
|
+
1.1 13 Dec 2013 Fix comments in test code
|
34
|
+
1.2 14 Dec 2013 Determine endianess at run time
|
35
|
+
1.3 15 Dec 2013 Add eight-byte processing for big endian as well
|
36
|
+
Make use of the pthread library optional
|
37
|
+
1.4 16 Dec 2013 Make once variable volatile for limited thread protection
|
38
|
+
*/
|
39
|
+
|
40
|
+
#include <stdio.h>
|
41
|
+
#include <inttypes.h>
|
42
|
+
#include <assert.h>
|
43
|
+
|
44
|
+
/* 64-bit CRC polynomial with these coefficients, but reversed:
|
45
|
+
64, 62, 57, 55, 54, 53, 52, 47, 46, 45, 40, 39, 38, 37, 35, 33, 32,
|
46
|
+
31, 29, 27, 24, 23, 22, 21, 19, 17, 13, 12, 10, 9, 7, 4, 1, 0 */
|
47
|
+
#define POLY UINT64_C(0xc96c5795d7870f42)
|
48
|
+
|
49
|
+
/* Tables for CRC calculation -- filled in by initialization functions that are
|
50
|
+
called once. These could be replaced by constant tables generated in the
|
51
|
+
same way. There are two tables, one for each endianess. Since these are
|
52
|
+
static, i.e. local, one should be compiled out of existence if the compiler
|
53
|
+
can evaluate the endianess check in crc64() at compile time. */
|
54
|
+
static uint64_t crc64_little_table[8][256];
|
55
|
+
static uint64_t crc64_big_table[8][256];
|
56
|
+
|
57
|
+
/* Fill in the CRC-64 constants table. */
|
58
|
+
static void crc64_init(uint64_t table[][256])
|
59
|
+
{
|
60
|
+
unsigned n, k;
|
61
|
+
uint64_t crc;
|
62
|
+
|
63
|
+
/* generate CRC-64's for all single byte sequences */
|
64
|
+
for (n = 0; n < 256; n++) {
|
65
|
+
crc = n;
|
66
|
+
for (k = 0; k < 8; k++)
|
67
|
+
crc = crc & 1 ? POLY ^ (crc >> 1) : crc >> 1;
|
68
|
+
table[0][n] = crc;
|
69
|
+
}
|
70
|
+
|
71
|
+
/* generate CRC-64's for those followed by 1 to 7 zeros */
|
72
|
+
for (n = 0; n < 256; n++) {
|
73
|
+
crc = table[0][n];
|
74
|
+
for (k = 1; k < 8; k++) {
|
75
|
+
crc = table[0][crc & 0xff] ^ (crc >> 8);
|
76
|
+
table[k][n] = crc;
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
/* This function is called once to initialize the CRC-64 table for use on a
|
82
|
+
little-endian architecture. */
|
83
|
+
static void crc64_little_init(void)
|
84
|
+
{
|
85
|
+
crc64_init(crc64_little_table);
|
86
|
+
}
|
87
|
+
|
88
|
+
/* Reverse the bytes in a 64-bit word. */
|
89
|
+
static inline uint64_t rev8(uint64_t a)
|
90
|
+
{
|
91
|
+
uint64_t m;
|
92
|
+
|
93
|
+
m = UINT64_C(0xff00ff00ff00ff);
|
94
|
+
a = ((a >> 8) & m) | (a & m) << 8;
|
95
|
+
m = UINT64_C(0xffff0000ffff);
|
96
|
+
a = ((a >> 16) & m) | (a & m) << 16;
|
97
|
+
return a >> 32 | a << 32;
|
98
|
+
}
|
99
|
+
|
100
|
+
/* This function is called once to initialize the CRC-64 table for use on a
|
101
|
+
big-endian architecture. */
|
102
|
+
static void crc64_big_init(void)
|
103
|
+
{
|
104
|
+
unsigned k, n;
|
105
|
+
|
106
|
+
crc64_init(crc64_big_table);
|
107
|
+
for (k = 0; k < 8; k++)
|
108
|
+
for (n = 0; n < 256; n++)
|
109
|
+
crc64_big_table[k][n] = rev8(crc64_big_table[k][n]);
|
110
|
+
}
|
111
|
+
|
112
|
+
/* init table once */
|
113
|
+
void crc64_init_once(void)
|
114
|
+
{
|
115
|
+
crc64_little_init();
|
116
|
+
crc64_big_init();
|
117
|
+
}
|
118
|
+
|
119
|
+
/* Calculate a CRC-64 eight bytes at a time on a little-endian architecture. */
|
120
|
+
static inline uint64_t crc64_little(uint64_t crc, void *buf, size_t len)
|
121
|
+
{
|
122
|
+
unsigned char *next = (unsigned char *) buf;
|
123
|
+
|
124
|
+
crc = ~crc;
|
125
|
+
while (len && ((uintptr_t)next & 7) != 0) {
|
126
|
+
crc = crc64_little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
|
127
|
+
len--;
|
128
|
+
}
|
129
|
+
while (len >= 8) {
|
130
|
+
crc ^= *(uint64_t *)next;
|
131
|
+
crc = crc64_little_table[7][crc & 0xff] ^
|
132
|
+
crc64_little_table[6][(crc >> 8) & 0xff] ^
|
133
|
+
crc64_little_table[5][(crc >> 16) & 0xff] ^
|
134
|
+
crc64_little_table[4][(crc >> 24) & 0xff] ^
|
135
|
+
crc64_little_table[3][(crc >> 32) & 0xff] ^
|
136
|
+
crc64_little_table[2][(crc >> 40) & 0xff] ^
|
137
|
+
crc64_little_table[1][(crc >> 48) & 0xff] ^
|
138
|
+
crc64_little_table[0][crc >> 56];
|
139
|
+
next += 8;
|
140
|
+
len -= 8;
|
141
|
+
}
|
142
|
+
while (len) {
|
143
|
+
crc = crc64_little_table[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
|
144
|
+
len--;
|
145
|
+
}
|
146
|
+
return ~crc;
|
147
|
+
}
|
148
|
+
|
149
|
+
/* Calculate a CRC-64 eight bytes at a time on a big-endian architecture. */
|
150
|
+
static inline uint64_t crc64_big(uint64_t crc, void *buf, size_t len)
|
151
|
+
{
|
152
|
+
unsigned char *next = (unsigned char *) buf;
|
153
|
+
|
154
|
+
crc = ~rev8(crc);
|
155
|
+
while (len && ((uintptr_t)next & 7) != 0) {
|
156
|
+
crc = crc64_big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
|
157
|
+
len--;
|
158
|
+
}
|
159
|
+
while (len >= 8) {
|
160
|
+
crc ^= *(uint64_t *)next;
|
161
|
+
crc = crc64_big_table[0][crc & 0xff] ^
|
162
|
+
crc64_big_table[1][(crc >> 8) & 0xff] ^
|
163
|
+
crc64_big_table[2][(crc >> 16) & 0xff] ^
|
164
|
+
crc64_big_table[3][(crc >> 24) & 0xff] ^
|
165
|
+
crc64_big_table[4][(crc >> 32) & 0xff] ^
|
166
|
+
crc64_big_table[5][(crc >> 40) & 0xff] ^
|
167
|
+
crc64_big_table[6][(crc >> 48) & 0xff] ^
|
168
|
+
crc64_big_table[7][crc >> 56];
|
169
|
+
next += 8;
|
170
|
+
len -= 8;
|
171
|
+
}
|
172
|
+
while (len) {
|
173
|
+
crc = crc64_big_table[0][(crc >> 56) ^ *next++] ^ (crc << 8);
|
174
|
+
len--;
|
175
|
+
}
|
176
|
+
return ~rev8(crc);
|
177
|
+
}
|
178
|
+
|
179
|
+
/* Return the CRC-64 of buf[0..len-1] with initial crc, processing eight bytes
|
180
|
+
at a time. This selects one of two routines depending on the endianess of
|
181
|
+
the architecture. A good optimizing compiler will determine the endianess
|
182
|
+
at compile time if it can, and get rid of the unused code and table. If the
|
183
|
+
endianess can be changed at run time, then this code will handle that as
|
184
|
+
well, initializing and using two tables, if called upon to do so. */
|
185
|
+
uint64_t crc64(uint64_t crc, void *buf, size_t len)
|
186
|
+
{
|
187
|
+
uint64_t n = 1;
|
188
|
+
|
189
|
+
return *(char *)&n ? crc64_little(crc, buf, len) :
|
190
|
+
crc64_big(crc, buf, len);
|
191
|
+
}
|
192
|
+
|
193
|
+
#define GF2_DIM 64 /* dimension of GF(2) vectors (length of CRC) */
|
194
|
+
|
195
|
+
static uint64_t gf2_matrix_times(uint64_t *mat, uint64_t vec)
|
196
|
+
{
|
197
|
+
uint64_t sum;
|
198
|
+
|
199
|
+
sum = 0;
|
200
|
+
while (vec) {
|
201
|
+
if (vec & 1)
|
202
|
+
sum ^= *mat;
|
203
|
+
vec >>= 1;
|
204
|
+
mat++;
|
205
|
+
}
|
206
|
+
return sum;
|
207
|
+
}
|
208
|
+
|
209
|
+
static void gf2_matrix_square(uint64_t *square, uint64_t *mat)
|
210
|
+
{
|
211
|
+
unsigned n;
|
212
|
+
|
213
|
+
for (n = 0; n < GF2_DIM; n++)
|
214
|
+
square[n] = gf2_matrix_times(mat, mat[n]);
|
215
|
+
}
|
216
|
+
|
217
|
+
/* Return the CRC-64 of two sequential blocks, where crc1 is the CRC-64 of the
|
218
|
+
first block, crc2 is the CRC-64 of the second block, and len2 is the length
|
219
|
+
of the second block. */
|
220
|
+
uint64_t crc64_combine(uint64_t crc1, uint64_t crc2, uintmax_t len2)
|
221
|
+
{
|
222
|
+
unsigned n;
|
223
|
+
uint64_t row;
|
224
|
+
uint64_t even[GF2_DIM]; /* even-power-of-two zeros operator */
|
225
|
+
uint64_t odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
226
|
+
|
227
|
+
/* degenerate case */
|
228
|
+
if (len2 == 0)
|
229
|
+
return crc1;
|
230
|
+
|
231
|
+
/* put operator for one zero bit in odd */
|
232
|
+
odd[0] = POLY; /* CRC-64 polynomial */
|
233
|
+
row = 1;
|
234
|
+
for (n = 1; n < GF2_DIM; n++) {
|
235
|
+
odd[n] = row;
|
236
|
+
row <<= 1;
|
237
|
+
}
|
238
|
+
|
239
|
+
/* put operator for two zero bits in even */
|
240
|
+
gf2_matrix_square(even, odd);
|
241
|
+
|
242
|
+
/* put operator for four zero bits in odd */
|
243
|
+
gf2_matrix_square(odd, even);
|
244
|
+
|
245
|
+
/* apply len2 zeros to crc1 (first square will put the operator for one
|
246
|
+
zero byte, eight zero bits, in even) */
|
247
|
+
do {
|
248
|
+
/* apply zeros operator for this bit of len2 */
|
249
|
+
gf2_matrix_square(even, odd);
|
250
|
+
if (len2 & 1)
|
251
|
+
crc1 = gf2_matrix_times(even, crc1);
|
252
|
+
len2 >>= 1;
|
253
|
+
|
254
|
+
/* if no more bits set, then done */
|
255
|
+
if (len2 == 0)
|
256
|
+
break;
|
257
|
+
|
258
|
+
/* another iteration of the loop with odd and even swapped */
|
259
|
+
gf2_matrix_square(odd, even);
|
260
|
+
if (len2 & 1)
|
261
|
+
crc1 = gf2_matrix_times(odd, crc1);
|
262
|
+
len2 >>= 1;
|
263
|
+
|
264
|
+
/* if no more bits set, then done */
|
265
|
+
} while (len2 != 0);
|
266
|
+
|
267
|
+
/* return combined crc */
|
268
|
+
crc1 ^= crc2;
|
269
|
+
return crc1;
|
270
|
+
}
|
data/ext/crcx/crcx.c
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#include "crcx.h"
|
2
|
+
|
3
|
+
void Init_crcx(){
|
4
|
+
VALUE mAliyun = Qnil;
|
5
|
+
VALUE CrcX = Qnil;
|
6
|
+
|
7
|
+
crc64_init_once();
|
8
|
+
|
9
|
+
mAliyun = rb_define_module("Aliyun");
|
10
|
+
CrcX = rb_define_module_under(mAliyun, "CrcX");
|
11
|
+
rb_define_module_function(CrcX, "crc64", crc64_wrapper, 3);
|
12
|
+
rb_define_module_function(CrcX, "crc64_combine", crc64_combine_wrapper, 3);
|
13
|
+
}
|
14
|
+
|
15
|
+
void check_num_type(VALUE crc_value)
|
16
|
+
{
|
17
|
+
if (T_BIGNUM == TYPE(crc_value)) {
|
18
|
+
Check_Type(crc_value, T_BIGNUM);
|
19
|
+
}
|
20
|
+
else {
|
21
|
+
Check_Type(crc_value, T_FIXNUM);
|
22
|
+
}
|
23
|
+
return ;
|
24
|
+
}
|
25
|
+
|
26
|
+
VALUE crc64_wrapper(VALUE self, VALUE init_crc, VALUE buffer, VALUE size)
|
27
|
+
{
|
28
|
+
uint64_t crc_value = 0;
|
29
|
+
|
30
|
+
check_num_type(init_crc);
|
31
|
+
check_num_type(size);
|
32
|
+
Check_Type(buffer, T_STRING);
|
33
|
+
crc_value = crc64(NUM2ULL(init_crc), (void *)RSTRING_PTR(buffer), NUM2ULL(size));
|
34
|
+
return ULL2NUM(crc_value);
|
35
|
+
}
|
36
|
+
|
37
|
+
VALUE crc64_combine_wrapper(VALUE self, VALUE crc1, VALUE crc2, VALUE len2)
|
38
|
+
{
|
39
|
+
uint64_t crc_value = 0;
|
40
|
+
check_num_type(crc1);
|
41
|
+
check_num_type(crc2);
|
42
|
+
check_num_type(len2);
|
43
|
+
crc_value = crc64_combine(NUM2ULL(crc1), NUM2ULL(crc2), NUM2ULL(len2));
|
44
|
+
return ULL2NUM(crc_value);
|
45
|
+
}
|
data/ext/crcx/crcx.h
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
uint64_t crc64(uint64_t crc, void *buf, size_t len);
|
4
|
+
uint64_t crc64_combine(uint64_t crc1, uint64_t crc2, uintmax_t len2);
|
5
|
+
void crc64_init_once(void);
|
6
|
+
|
7
|
+
VALUE crc64_wrapper(VALUE self, VALUE init_crc, VALUE buffer, VALUE size);
|
8
|
+
VALUE crc64_combine_wrapper(VALUE self, VALUE crc1, VALUE crc2, VALUE len2);
|
data/ext/crcx/extconf.rb
ADDED
data/lib/aliyun/oss.rb
CHANGED
data/lib/aliyun/oss/bucket.rb
CHANGED
@@ -639,6 +639,18 @@ module Aliyun
|
|
639
639
|
@protocol.sign(string_to_sign)
|
640
640
|
end
|
641
641
|
|
642
|
+
# Get the download crc status
|
643
|
+
# @return true(download crc enable) or false(download crc disable)
|
644
|
+
def download_crc_enable
|
645
|
+
@protocol.download_crc_enable
|
646
|
+
end
|
647
|
+
|
648
|
+
# Get the upload crc status
|
649
|
+
# @return true(upload crc enable) or false(upload crc disable)
|
650
|
+
def upload_crc_enable
|
651
|
+
@protocol.upload_crc_enable
|
652
|
+
end
|
653
|
+
|
642
654
|
private
|
643
655
|
# Infer the file's content type using MIME::Types
|
644
656
|
# @param file [String] the file path
|
@@ -655,7 +667,6 @@ module Aliyun
|
|
655
667
|
def get_cpt_file(file)
|
656
668
|
"#{File.expand_path(file)}.cpt"
|
657
669
|
end
|
658
|
-
|
659
670
|
end # Bucket
|
660
671
|
end # OSS
|
661
672
|
end # Aliyun
|
data/lib/aliyun/oss/client.rb
CHANGED
@@ -28,6 +28,10 @@ module Aliyun
|
|
28
28
|
# KEY SECRET,如果不填则会尝试匿名访问
|
29
29
|
# @option opts [Boolean] :cname [可选] 指定endpoint是否是用户绑
|
30
30
|
# 定的域名
|
31
|
+
# @option opts [Boolean] :upload_crc_enable [可选]指定上传处理
|
32
|
+
# 是否开启CRC校验,默认为开启(true)
|
33
|
+
# @option opts [Boolean] :download_crc_enable [可选]指定下载处理
|
34
|
+
# 是否开启CRC校验,默认为不开启(false)
|
31
35
|
# @option opts [String] :sts_token [可选] 指定STS的
|
32
36
|
# SecurityToken,如果指定,则使用STS授权访问
|
33
37
|
# @option opts [Fixnum] :open_timeout [可选] 指定建立连接的超时
|
data/lib/aliyun/oss/config.rb
CHANGED
@@ -11,7 +11,8 @@ module Aliyun
|
|
11
11
|
|
12
12
|
attrs :endpoint, :cname, :sts_token,
|
13
13
|
:access_key_id, :access_key_secret,
|
14
|
-
:open_timeout, :read_timeout
|
14
|
+
:open_timeout, :read_timeout,
|
15
|
+
:download_crc_enable, :upload_crc_enable
|
15
16
|
|
16
17
|
def initialize(opts = {})
|
17
18
|
super(opts)
|
@@ -19,6 +20,8 @@ module Aliyun
|
|
19
20
|
@access_key_id = @access_key_id.strip if @access_key_id
|
20
21
|
@access_key_secret = @access_key_secret.strip if @access_key_secret
|
21
22
|
normalize_endpoint if endpoint
|
23
|
+
@upload_crc_enable = (@upload_crc_enable == 'false' || @upload_crc_enable == false) ? false : true
|
24
|
+
@download_crc_enable = (@download_crc_enable == 'true' || @download_crc_enable == true) ? true : false
|
22
25
|
end
|
23
26
|
|
24
27
|
private
|
data/lib/aliyun/oss/download.rb
CHANGED
@@ -114,7 +114,7 @@ module Aliyun
|
|
114
114
|
|
115
115
|
parts = sync_get_all_parts
|
116
116
|
# concat all part files into the target file
|
117
|
-
File.open(@file, '
|
117
|
+
File.open(@file, 'wb') do |w|
|
118
118
|
parts.sort{ |x, y| x[:number] <=> y[:number] }.each do |p|
|
119
119
|
File.open(get_part_file(p)) do |r|
|
120
120
|
w.write(r.read(READ_SIZE)) until r.eof?
|
@@ -177,7 +177,7 @@ module Aliyun
|
|
177
177
|
logger.debug("Begin download part: #{p}")
|
178
178
|
|
179
179
|
part_file = get_part_file(p)
|
180
|
-
File.open(part_file, '
|
180
|
+
File.open(part_file, 'wb') do |w|
|
181
181
|
@protocol.get_object(
|
182
182
|
bucket, object,
|
183
183
|
@options.merge(range: p[:range])) { |chunk| w.write(chunk) }
|
data/lib/aliyun/oss/exception.rb
CHANGED
@@ -64,6 +64,12 @@ module Aliyun
|
|
64
64
|
class ClientError < Common::Exception
|
65
65
|
end # ClientError
|
66
66
|
|
67
|
+
##
|
68
|
+
# CrcInconsistentError will be raised after a upload operation,
|
69
|
+
# when the local crc is inconsistent with the response crc from server.
|
70
|
+
#
|
71
|
+
class CrcInconsistentError < Common::Exception; end
|
72
|
+
|
67
73
|
##
|
68
74
|
# FileInconsistentError happens in a resumable upload transaction,
|
69
75
|
# when the file to upload has changed during the uploading
|