-
Notifications
You must be signed in to change notification settings - Fork 54
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
feat(blob): multipart upload #71
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering how we can change API routes to remove query params.
Just an idea:
/blob/multipart/[...pathname].post.ts
create a multip part upload/blob/multipart/[...pathname]/[uploadId]/[partNumber].put.ts
put a part/blob/multipart/[...pathname]/[uploadId]/complete.post.ts
complete upload task
it is from the wroked, as their member said:
so we can safity ignore this |
sadily radix3 doesn't support this route import { createRouter } from "radix3"
const router = createRouter()
router.insert('/api/blob/multipart/**:pathname/', { payload: 'not this' })
router.insert('/api/blob/multipart/**:pathname/:uploadId/:partNumber', { payload: 'found' })
const res = router.lookup('/api/blob/multipart/hello.txt/id/1')
console.log(res) returns
so I just make create / complete in different route |
Thank you so much @Teages I think to move forward, I would like to have a await hubBlob().put('movie.mp4', file, {
multipart: true
}) As well as updating the documentation for it. As a bonus, it would be nice to find a way to have a Vue composable as well: useUpload(`/api/blob/multipart/${file.name}`).upload(file, { multipart: true }) |
I think it maybe not not be very useful, hubBlob runs on nitro, which is running in cloudflare worker, it should have the most stable connection to cloudflare r2. The limitation of direct upload seems to be 300mb, but woker only have 128mb memory. I can't see any need for workers to upload to r2 in multipart. It should be the same for other platforms.
Yes I think so, but it affects flexibility, I didn't see nuxt hub have provided any upload api except hub proxy. Or we can provide a composable like this: const { progress } = useMultipartUpload({
file,
partSize: 10 * 1024 * 1024, // 10MB
throttle: 2, // 2 concurrent uploads
}, ({partNumber, body}) => $fetch()) |
Makes sense, let's skip it. What about: const { progress, isComplete } = useMultipartUpload(file, {
partSize: 10 * 1024 * 1024, // 10MB
throttle: 2, // 2 concurrent uploads
}, ({ partNumber, chunkBody }) => $fetch()) It would be nice to have the second parameter as optional: const { progress, isComplete } = useMultipartUpload(file, ({ partNumber, chunkBody }) => $fetch()) So it could use defaults we can define, wdyt? |
well I designed a composable creater: export const useMultipartUpload = createMultipartUploader({
create: (file) => $fetch(),
upload: ({ partNumber, chunkBody }, { pathname, uploadId }) => $fetch(),
complete: (parts, { pathname, uploadId }) => $fetch(),
abort: ({ pathname, uploadId }) => $fetch(),
partSize: 10 * 1024 * 1024, // 10MB
concurrent: 2, // 2 concurrent uploads
maxRetry: 3,
}) then upload file in just two lines: const { completed, progress, cancel } = useMultipartUpload(file)
const result = await completed |
Thank you so much for your work, we are getting close! I've been thinking, what about using the
We could have an abstraction similar to this: // server/api/blob/multipart/[action]/[...pathname].ts
export default eventHandler(async (event) => {
await hubBlob().handleMultipartUpload(event, {
// options...
addRandomSuffix: true
})
}) This will avoid creating 4 files to handle multipart upload, and it should also simplify the createMultipartUploader function, I would rename it to const upload = useMulipartUpload('/api/blob/multipart', {
partSize: 10 * 1024 * 1024, // 10MB
concurrent: 2, // 2 concurrent uploads
maxRetry: 3,
})
const { progress, completed, abort } = upload(file) Also, would you mind updating the |
That would be great, what options do we need for // server/api/blob/multipart/[action]/[...pathname].ts
export default eventHandler(async (event) => {
const actions = getRouterParam(event, 'action')
// do something before handle
return await hubBlob().handleMultipartUpload(event)
}) and most upload need authentication, I want to allow overwrite ofetch options of interface UseMulipartUploadOptions {
//... some else
fetchOptions: Omit<FetchOptions, 'body' | 'parseResponse' | 'responseType'>
} |
The goal of exposing a function is that they can do whatever they want before and after the function instead of exposing an API route :) I like the |
You are very fast @Teages 🚀 Happy to resolve the conflicts? 🙏 |
oops seems I messed up, I need some time to solve |
ok it looks good now |
cc @farnabaz |
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Sébastien Chopin <seb@nuxtlabs.com> Co-authored-by: Sébastien Chopin <seb@nuxt.com> Co-authored-by: Farnabaz <farnabaz@gmail.com>
Resolves #66
This pull request added multipart upload api and its proxy route.
Also fixed a type error on
proxyHubBlob
, it breaks the type checkdid some check in playground,
not check the proxy api yet.Checked in remote proxy, works well except the
contentType
not included in the complete response (but it returns in dev server), maybe it takes time for r2 to determine the type