Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Transloadit-hosted Companion with other uploaders #5558

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion packages/@uppy/aws-s3/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -923,10 +923,24 @@ export default class AwsS3Multipart<

// eslint-disable-next-line class-methods-use-this
#getCompanionClientArgs(file: UppyFile<M, B>) {
const opts = { ...this.opts }

// When you .use(AwsS3) with .use(Transloadit, { companionOnly: true }),
// local files are uploaded with this plugin and remote files with the Transloadit plugin.
// Since the Transloadit plugin uses the tus plugin underneath, it's possible to have file.tus
// even though we are in this plugin.
// @ts-expect-error typed in @uppy/tus
if (file.tus) {
// @ts-expect-error typed in @uppy/tus
Object.assign(opts, file.tus)
}

return {
...file.remote?.body,
protocol: 's3-multipart',
endpoint: opts.endpoint,
protocol: this.uppy.getState().remoteUploader || 's3-multipart',
size: file.data.size,
headers: opts.headers,
metadata: file.meta,
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/@uppy/core/src/Uppy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ export interface State<M extends Meta, B extends Body>
currentUploads: Record<string, CurrentUpload<M, B>>
allowNewUpload: boolean
recoveredState: null | Required<Pick<State<M, B>, 'files' | 'currentUploads'>>
remoteUploader?: 'tus' | 's3-multipart' | 'multipart'
error: string | null
files: {
[key: string]: UppyFile<M, B>
Expand Down
35 changes: 26 additions & 9 deletions packages/@uppy/transloadit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ export interface TransloaditOptions<M extends Meta, B extends Body>
waitForMetadata?: boolean
importFromUploadURLs?: boolean
alwaysRunAssembly?: boolean
/**
* Only use Transloadit for remote file uploads (such as from Google Drive).
* Enabling this means you have to install another plugin for local files,
* such as @uppy/aws-s3 or @uppy/xhr-upload.
*/
companionOnly?: boolean
limit?: number
clientName?: string | null
retryDelays?: number[]
Expand All @@ -145,6 +151,7 @@ const defaultOptions = {
waitForMetadata: false,
alwaysRunAssembly: false,
importFromUploadURLs: false,
companionOnly: false,
limit: 20,
retryDelays: [7_000, 10_000, 15_000, 20_000],
clientName: null,
Expand Down Expand Up @@ -295,6 +302,13 @@ export default class Transloadit<

this.i18nInit()

if (this.opts.companionOnly) {
// Transloadit is only a pre and post processor.
// To let Transloadit hosted Companion download the file,
// we instruct any other upload plugin to use tus for remote uploads.
this.uppy.setState({ remoteUploader: 'tus' })
}

this.client = new Client({
service: this.opts.service,
client: this.#getClientVersion(),
Expand Down Expand Up @@ -802,26 +816,30 @@ export default class Transloadit<

assemblyOptions.fields ??= {}
validateParams(assemblyOptions.params)
const ids =
this.opts.companionOnly ?
fileIDs.filter((id) => this.uppy.getFile(id).isRemote)
: fileIDs

try {
const assembly =
// this.assembly can already be defined if we recovered files with Golden Retriever (this.#onRestored)
this.assembly ?? (await this.#createAssembly(fileIDs, assemblyOptions))
this.assembly ?? (await this.#createAssembly(ids, assemblyOptions))

if (assembly == null)
throw new Error('All files were canceled after assembly was created')

if (this.opts.importFromUploadURLs) {
await this.#reserveFiles(assembly, fileIDs)
await this.#reserveFiles(assembly, ids)
}
fileIDs.forEach((fileID) => {
ids.forEach((fileID) => {
const file = this.uppy.getFile(fileID)
this.uppy.emit('preprocess-complete', file)
})
this.#createAssemblyWatcher(assembly.status.assembly_id)
this.#connectAssembly(assembly, fileIDs)
this.#connectAssembly(assembly, ids)
} catch (err) {
fileIDs.forEach((fileID) => {
ids.forEach((fileID) => {
const file = this.uppy.getFile(fileID)
// Clear preprocessing state when the Assembly could not be created,
// otherwise the UI gets confused about the lingering progress keys
Expand Down Expand Up @@ -937,9 +955,9 @@ export default class Transloadit<
if (this.opts.importFromUploadURLs) {
// No uploader needed when importing; instead we take the upload URL from an existing uploader.
this.uppy.on('upload-success', this.#onFileUploadURLAvailable)
} else {
// we don't need it here.
// the regional endpoint from the Transloadit API before we can set it.
// If companionOnly is true, another uploader plugin is installed for local uploads
// and we only use Transloadit to create an assembly for the remote files.
} else if (!this.opts.companionOnly) {
this.uppy.use(Tus, {
// Disable tus-js-client fingerprinting, otherwise uploading the same file at different times
// will upload to an outdated Assembly, and we won't get socket events for it.
Expand All @@ -954,7 +972,6 @@ export default class Transloadit<
// Send all metadata to Transloadit. Metadata set by the user
// ends up as in the template as `file.user_meta`
allowedMetaFields: true,
// Pass the limit option to @uppy/tus
limit: this.opts.limit,
rateLimitedQueue: this.#rateLimitedQueue,
retryDelays: this.opts.retryDelays,
Expand Down
12 changes: 11 additions & 1 deletion packages/@uppy/xhr-upload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,19 @@ export default class XHRUpload<
opts.allowedMetaFields,
file.meta,
)
// When you .use(AwsS3) with .use(Transloadit, { companionOnly: true }),
// local files are uploaded with this plugin and remote files with the Transloadit plugin.
// Since the Transloadit plugin uses the tus plugin underneath, it's possible to have file.tus
// even though we are in this plugin.
// @ts-expect-error typed in @uppy/tus
if (file.tus) {
// @ts-expect-error typed in @uppy/tus
Object.assign(opts, file.tus)
}

return {
...file.remote?.body,
protocol: 'multipart',
protocol: this.uppy.getState().remoteUploader || 'multipart',
endpoint: opts.endpoint,
size: file.data.size,
fieldname: opts.fieldName,
Expand Down
18 changes: 17 additions & 1 deletion private/dev/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export default () => {
.use(Webdav, {
target: Dashboard,
companionUrl: COMPANION_URL,
companionAllowedHosts
companionAllowedHosts,
})
.use(Audio, {
target: Dashboard,
Expand All @@ -195,6 +195,15 @@ export default () => {
shouldUseMultipart: false,
})
break
case 's3-with-transloadit-companion':
uppyDashboard.use(AwsS3, { endpoint: COMPANION_URL })
uppyDashboard.use(Transloadit, {
service: TRANSLOADIT_SERVICE_URL,
waitForEncoding: true,
assemblyOptions,
companionOnly: true,
})
break
case 's3-multipart':
uppyDashboard.use(AwsS3, {
endpoint: COMPANION_URL,
Expand All @@ -207,6 +216,12 @@ export default () => {
limit: 6,
bundle: false,
})
uppyDashboard.use(Transloadit, {
service: TRANSLOADIT_SERVICE_URL,
waitForEncoding: true,
assemblyOptions,
companionOnly: true,
})
break
case 'transloadit':
uppyDashboard.use(Transloadit, {
Expand All @@ -221,6 +236,7 @@ export default () => {
waitForEncoding: true,
importFromUploadURLs: true,
assemblyOptions,
companionOnly: true,
})
break
case 'transloadit-xhr':
Expand Down
Loading