or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cloud-providers.mdcore-uppy.mdfile-sources.mdindex.mdplugin-architecture.mdtypescript-support.mdui-plugins.mdupload-handlers.mdutility-plugins.md

upload-handlers.mddocs/

0

# Upload Handlers

1

2

Upload handler plugins manage the actual file upload process, supporting various protocols and destinations including resumable uploads, traditional HTTP uploads, and cloud storage services.

3

4

## Capabilities

5

6

### Resumable Uploads

7

8

Protocols that support resumable uploads for reliability and performance.

9

10

```typescript { .api }

11

/**

12

* Tus resumable upload protocol implementation

13

*/

14

class Tus<M extends Meta = {}, B extends Body = {}> extends BasePlugin<TusOptions> {

15

constructor(uppy: Uppy<M, B>, options?: TusOptions);

16

}

17

18

interface TusOptions {

19

endpoint: string;

20

headers?: { [key: string]: string };

21

chunkSize?: number;

22

withCredentials?: boolean;

23

overridePatchMethod?: boolean;

24

retryDelays?: number[];

25

parallelUploads?: number;

26

removeFingerprintOnSuccess?: boolean;

27

uploadDataDuringCreation?: boolean;

28

urlStorage?: TusUrlStorage;

29

fileReader?: TusFileReader;

30

onBeforeRequest?: (req: HttpRequest) => void;

31

onAfterResponse?: (req: HttpRequest, res: HttpResponse) => void;

32

limit?: number;

33

onShouldRetry?: (err: Error, retryAttempt: number, options: TusOptions) => boolean;

34

metaFields?: string[];

35

allowedMetaFields?: string[];

36

locale?: Locale;

37

}

38

39

interface TusUrlStorage {

40

findAllUploads(): Promise<{ [key: string]: string }>;

41

findUploadsByFingerprint(fingerprint: string): Promise<string[]>;

42

removeUpload(urlStorageKey: string): Promise<void>;

43

addUpload(fingerprint: string, upload: { uploadUrl: string; urlStorageKey: string }): Promise<void>;

44

}

45

46

interface TusFileReader {

47

slice(file: Blob, start: number, end: number): Blob;

48

}

49

```

50

51

**Usage Example:**

52

53

```typescript

54

import { Uppy, Tus } from "uppy";

55

56

const uppy = new Uppy()

57

.use(Tus, {

58

endpoint: 'https://tusd.tusdemo.net/files/',

59

chunkSize: 1024 * 1024, // 1MB chunks

60

retryDelays: [0, 1000, 3000, 5000],

61

parallelUploads: 3,

62

removeFingerprintOnSuccess: true,

63

headers: {

64

'Authorization': 'Bearer ' + authToken

65

},

66

onBeforeRequest: (req) => {

67

// Modify request before sending

68

req.setHeader('X-Custom-Header', 'value');

69

},

70

onAfterResponse: (req, res) => {

71

// Handle response

72

console.log('Upload progress response:', res.getStatus());

73

}

74

});

75

```

76

77

### Traditional HTTP Uploads

78

79

Standard HTTP upload implementations using XMLHttpRequest or fetch.

80

81

```typescript { .api }

82

/**

83

* XHR upload implementation for standard HTTP endpoints

84

*/

85

class XHRUpload<M extends Meta = {}, B extends Body = {}> extends BasePlugin<XHRUploadOptions<M, B>> {

86

constructor(uppy: Uppy<M, B>, options?: XHRUploadOptions<M, B>);

87

}

88

89

interface XHRUploadOptions<M extends Meta = {}, B extends Body = {}> {

90

endpoint: string;

91

method?: 'POST' | 'PUT' | 'PATCH';

92

formData?: boolean;

93

fieldName?: string;

94

allowedMetaFields?: string[];

95

headers?: { [key: string]: string } | ((file: UppyFile<M, B>) => { [key: string]: string });

96

bundle?: boolean;

97

withCredentials?: boolean;

98

timeout?: number;

99

limit?: number;

100

responseType?: '' | 'text' | 'json' | 'blob' | 'document' | 'arraybuffer';

101

responseUrlFieldName?: string;

102

getResponseData?: (responseText: string, response: XMLHttpRequest) => B;

103

getResponseError?: (responseText: string, response: XMLHttpRequest) => Error;

104

onBeforeRequest?: (xhr: XMLHttpRequest, file: UppyFile<M, B>) => void;

105

validateStatus?: (status: number, responseText: string, response: XMLHttpRequest) => boolean;

106

locale?: Locale;

107

}

108

```

109

110

**Usage Examples:**

111

112

```typescript

113

// Standard form data upload

114

uppy.use(XHRUpload, {

115

endpoint: '/api/upload',

116

method: 'POST',

117

formData: true,

118

fieldName: 'file',

119

headers: {

120

'X-CSRF-Token': csrfToken

121

},

122

allowedMetaFields: ['name', 'caption', 'description'],

123

limit: 5, // Max 5 concurrent uploads

124

timeout: 30000, // 30 second timeout

125

126

onBeforeRequest: (xhr, file) => {

127

// Add file-specific headers

128

xhr.setRequestHeader('X-File-Name', file.name);

129

xhr.setRequestHeader('X-File-Size', file.size.toString());

130

},

131

132

getResponseData: (responseText, response) => {

133

// Parse custom response format

134

return JSON.parse(responseText);

135

},

136

137

validateStatus: (status, responseText, response) => {

138

// Custom success validation

139

return status >= 200 && status < 300;

140

}

141

});

142

143

// JSON upload with custom headers per file

144

uppy.use(XHRUpload, {

145

endpoint: '/api/files',

146

method: 'PUT',

147

formData: false,

148

headers: (file) => ({

149

'Content-Type': file.type,

150

'X-File-ID': file.id,

151

'Authorization': `Bearer ${getTokenForFile(file)}`

152

}),

153

responseType: 'json'

154

});

155

```

156

157

### Cloud Storage Direct Upload

158

159

Direct upload to cloud storage services bypassing your server.

160

161

```typescript { .api }

162

/**

163

* AWS S3 direct upload implementation

164

*/

165

class AwsS3<M extends Meta = {}, B extends Body = {}> extends BasePlugin<AwsS3Options> {

166

constructor(uppy: Uppy<M, B>, options?: AwsS3Options);

167

}

168

169

interface AwsS3Options {

170

companionUrl?: string;

171

companionHeaders?: { [key: string]: string };

172

companionCookiesRule?: string;

173

getUploadParameters?: (file: UppyFile<any, any>) => Promise<S3UploadParameters> | S3UploadParameters;

174

timeout?: number;

175

limit?: number;

176

metaFields?: string[];

177

allowedMetaFields?: string[];

178

locale?: Locale;

179

}

180

181

interface S3UploadParameters {

182

method?: 'POST' | 'PUT';

183

url: string;

184

fields?: { [key: string]: string };

185

headers?: { [key: string]: string };

186

}

187

```

188

189

**Usage Examples:**

190

191

```typescript

192

// S3 upload with companion server

193

uppy.use(AwsS3, {

194

companionUrl: 'https://companion.uppy.io',

195

limit: 3,

196

timeout: 60000

197

});

198

199

// S3 upload with custom parameters

200

uppy.use(AwsS3, {

201

getUploadParameters: async (file) => {

202

// Get signed URL from your server

203

const response = await fetch('/api/s3-params', {

204

method: 'POST',

205

headers: {

206

'Content-Type': 'application/json'

207

},

208

body: JSON.stringify({

209

filename: file.name,

210

contentType: file.type,

211

size: file.size

212

})

213

});

214

215

const data = await response.json();

216

217

return {

218

method: 'POST',

219

url: data.url,

220

fields: data.fields,

221

headers: data.headers

222

};

223

},

224

225

allowedMetaFields: ['caption', 'description'],

226

limit: 5

227

});

228

```

229

230

### Processing Services

231

232

Upload handlers that integrate with file processing and encoding services.

233

234

```typescript { .api }

235

/**

236

* Transloadit encoding service integration

237

*/

238

class Transloadit<M extends Meta = {}, B extends Body = {}> extends BasePlugin<TransloaditOptions> {

239

constructor(uppy: Uppy<M, B>, options?: TransloaditOptions);

240

}

241

242

interface TransloaditOptions {

243

assemblyOptions?: AssemblyOptions | ((file: UppyFile<M, B>) => AssemblyOptions);

244

waitForEncoding?: boolean;

245

waitForMetadata?: boolean;

246

alwaysRunAssembly?: boolean;

247

importFromUploadURLs?: boolean;

248

signature?: string;

249

params?: AssemblyParameters | ((file: UppyFile<M, B>) => AssemblyParameters);

250

fields?: { [key: string]: string } | ((file: UppyFile<M, B>) => { [key: string]: string });

251

limit?: number;

252

locale?: Locale;

253

}

254

255

interface AssemblyOptions {

256

params: AssemblyParameters;

257

signature?: string;

258

fields?: { [key: string]: string };

259

}

260

261

interface AssemblyParameters {

262

auth: {

263

key: string;

264

expires?: string;

265

};

266

template_id?: string;

267

steps?: { [key: string]: StepOptions };

268

notify_url?: string;

269

}

270

271

interface StepOptions {

272

robot: string;

273

use?: string | string[];

274

[key: string]: any;

275

}

276

```

277

278

**Usage Example:**

279

280

```typescript

281

// Transloadit with template

282

uppy.use(Transloadit, {

283

params: {

284

auth: { key: 'YOUR_TRANSLOADIT_KEY' },

285

template_id: 'YOUR_TEMPLATE_ID'

286

},

287

waitForEncoding: true,

288

289

// Dynamic assembly options per file

290

assemblyOptions: (file) => ({

291

params: {

292

auth: { key: 'YOUR_TRANSLOADIT_KEY' },

293

steps: {

294

resize: {

295

robot: '/image/resize',

296

width: file.meta.targetWidth || 800,

297

height: file.meta.targetHeight || 600,

298

resize_strategy: 'fit'

299

},

300

optimize: {

301

robot: '/image/optimize',

302

use: 'resize'

303

}

304

}

305

}

306

})

307

});

308

```

309

310

## Upload Handler Events

311

312

```typescript { .api }

313

// Upload lifecycle events

314

interface UploadHandlerEvents<M extends Meta = {}, B extends Body = {}> {

315

'upload-started': (file: UppyFile<M, B>) => void;

316

'upload-progress': (file: UppyFile<M, B>, progress: FileProgress) => void;

317

'upload-success': (file: UppyFile<M, B>, response: UploadSuccessResponse<B>) => void;

318

'upload-error': (file: UppyFile<M, B>, error: Error, response?: UploadErrorResponse<M, B>) => void;

319

'upload-retry': (file: UppyFile<M, B>) => void;

320

}

321

322

// Tus-specific events

323

interface TusEvents<M extends Meta = {}, B extends Body = {}> {

324

'tus:upload-created': (file: UppyFile<M, B>, upload: { uploadURL: string }) => void;

325

'tus:chunk-uploaded': (file: UppyFile<M, B>, chunk: { chunkNumber: number, chunkSize: number }) => void;

326

}

327

328

// S3-specific events

329

interface AwsS3Events<M extends Meta = {}, B extends Body = {}> {

330

's3:upload-created': (file: UppyFile<M, B>, upload: S3Upload) => void;

331

's3:upload-progress': (file: UppyFile<M, B>, progress: S3Progress) => void;

332

}

333

```

334

335

## Response Types

336

337

```typescript { .api }

338

interface UploadSuccessResponse<B extends Body = {}> {

339

status: number;

340

body: B;

341

uploadURL?: string;

342

}

343

344

interface UploadErrorResponse<M extends Meta = {}, B extends Body = {}> {

345

status: number;

346

body: any;

347

message?: string;

348

details?: string;

349

}

350

351

interface HttpRequest {

352

getMethod(): string;

353

getURL(): string;

354

setHeader(name: string, value: string): void;

355

getHeader(name: string): string | undefined;

356

setProgressHandler(handler: (bytesSent: number, bytesTotal: number) => void): void;

357

}

358

359

interface HttpResponse {

360

getStatus(): number;

361

getHeader(name: string): string | undefined;

362

getBody(): string;

363

}

364

```