uppy/examples/aws-nodejs/public/withCustomEndpoints.html
2024-06-13 14:55:12 +02:00

267 lines
8.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Uppy AWS upload example</title>
<link href="./uppy.min.css" rel="stylesheet" />
</head>
<body>
<h1>AWS upload example</h1>
<div id="uppy"></div>
<footer>
You seeing the complex example, with a backend that does not mimick a
Companion-like instance. See
<a href="./index.html">the simplified example</a> if you don't need custom
functions for handling communication with the backend.
</footer>
<noscript>You need JavaScript to run this example.</noscript>
<script type="module">
import { Uppy, Dashboard, AwsS3 } from './uppy.min.mjs'
/**
* This generator transforms a deep object into URL-encodable pairs
* to work with `URLSearchParams` on the client and `body-parser` on the server.
*/
function* serializeSubPart(key, value) {
if (typeof value !== 'object') {
yield [key, value]
return
}
if (Array.isArray(value)) {
for (const val of value) {
yield* serializeSubPart(`${key}[]`, val)
}
return
}
for (const [subkey, val] of Object.entries(value)) {
yield* serializeSubPart(key ? `${key}[${subkey}]` : subkey, val)
}
}
function serialize(data) {
// If you want to avoid preflight requests, use URL-encoded syntax:
return new URLSearchParams(serializeSubPart(null, data))
// If you don't care about additional preflight requests, you can also use:
// return JSON.stringify(data)
// You'd also have to add `Content-Type` header with value `application/json`.
}
{
const MiB = 0x10_00_00
const uppy = new Uppy()
.use(Dashboard, {
inline: true,
target: '#uppy',
})
.use(AwsS3, {
id: 'myAWSPlugin',
// Files that are more than 100MiB should be uploaded in multiple parts.
shouldUseMultipart: (file) => file.size > 100 * MiB,
/**
* This method tells Uppy how to retrieve a temporary token for signing on the client.
* Signing on the client is optional, you can also do the signing from the server.
*/
async getTemporarySecurityCredentials({ signal }) {
const response = await fetch('/s3/sts', { signal })
if (!response.ok)
throw new Error('Unsuccessful request', { cause: response })
return response.json()
},
// ========== Non-Multipart Uploads ==========
/**
* This method tells Uppy how to handle non-multipart uploads.
* If for some reason you want to only support multipart uploads,
* you don't need to implement it.
*/
async getUploadParameters(file, options) {
if (typeof crypto?.subtle === 'object') {
// If WebCrypto is available, let's do signing from the client.
return uppy
.getPlugin('myAWSPlugin')
.createSignedURL(file, options)
}
// Send a request to our Express.js signing endpoint.
const response = await fetch('/s3/sign', {
method: 'POST',
headers: {
accept: 'application/json',
},
body: serialize({
filename: file.name,
contentType: file.type,
}),
signal: options.signal,
})
if (!response.ok)
throw new Error('Unsuccessful request', { cause: response })
// Parse the JSON response.
const data = await response.json()
// Return an object in the correct shape.
return {
method: data.method,
url: data.url,
fields: {}, // For presigned PUT uploads, this should be left empty.
// Provide content type header required by S3
headers: {
'Content-Type': file.type,
},
}
},
// ========== Multipart Uploads ==========
// The following methods are only useful for multipart uploads:
// If you are not interested in multipart uploads, you don't need to
// implement them (you'd also need to set `shouldUseMultipart: false` though).
async createMultipartUpload(file, signal) {
signal?.throwIfAborted()
const metadata = {}
Object.keys(file.meta || {}).forEach((key) => {
if (file.meta[key] != null) {
metadata[key] = file.meta[key].toString()
}
})
const response = await fetch('/s3/multipart', {
method: 'POST',
// Send and receive JSON.
headers: {
accept: 'application/json',
},
body: serialize({
filename: file.name,
type: file.type,
metadata,
}),
signal,
})
if (!response.ok)
throw new Error('Unsuccessful request', { cause: response })
// Parse the JSON response.
const data = await response.json()
return data
},
async abortMultipartUpload(file, { key, uploadId, signal }) {
const filename = encodeURIComponent(key)
const uploadIdEnc = encodeURIComponent(uploadId)
const response = await fetch(
`/s3/multipart/${uploadIdEnc}?key=${filename}`,
{
method: 'DELETE',
signal,
},
)
if (!response.ok)
throw new Error('Unsuccessful request', { cause: response })
},
async signPart(file, options) {
if (typeof crypto?.subtle === 'object') {
// If WebCrypto, let's do signing from the client.
return uppy
.getPlugin('myAWSPlugin')
.createSignedURL(file, options)
}
const { uploadId, key, partNumber, signal } = options
signal?.throwIfAborted()
if (uploadId == null || key == null || partNumber == null) {
throw new Error(
'Cannot sign without a key, an uploadId, and a partNumber',
)
}
const filename = encodeURIComponent(key)
const response = await fetch(
`/s3/multipart/${uploadId}/${partNumber}?key=${filename}`,
{ signal },
)
if (!response.ok)
throw new Error('Unsuccessful request', { cause: response })
const data = await response.json()
return data
},
async listParts(file, { key, uploadId }, signal) {
signal?.throwIfAborted()
const filename = encodeURIComponent(key)
const response = await fetch(
`/s3/multipart/${uploadId}?key=${filename}`,
{ signal },
)
if (!response.ok)
throw new Error('Unsuccessful request', { cause: response })
const data = await response.json()
return data
},
async completeMultipartUpload(
file,
{ key, uploadId, parts },
signal,
) {
signal?.throwIfAborted()
const filename = encodeURIComponent(key)
const uploadIdEnc = encodeURIComponent(uploadId)
const response = await fetch(
`s3/multipart/${uploadIdEnc}/complete?key=${filename}`,
{
method: 'POST',
headers: {
accept: 'application/json',
},
body: serialize({ parts }),
signal,
},
)
if (!response.ok)
throw new Error('Unsuccessful request', { cause: response })
const data = await response.json()
return data
},
})
uppy.on('complete', (result) => {
console.log(
'Upload complete! Weve uploaded these files:',
result.successful,
)
})
uppy.on('upload-success', (file, data) => {
console.log(
'Upload success! Weve uploaded this file:',
file.meta['name'],
)
})
}
</script>
</body>
</html>