Giter VIP home page Giter VIP logo

react-uploady's Introduction

React Uploady Logo React Uploady Logo

Modern file-upload components & hooks for React.

npm version Build Status codecov status rpldy storybook lerna MIT License

Contents

Intro

React-Uploady is a lightweight library - enabling you to build (client-side) file-upload features with just a few lines of code. Uploady provides the foundations needed to upload files from the browser - The rest is up to you.

React-Uploady Demo

The philosophy behind this library is that it should be as simple as possible to use, yet customizable at every point. You can start simple, or you can configure just about every aspect of the upload flow. For this purpose, there are components, hooks, and plenty of features. You get to choose which ones you need and only install the dependencies required (See Packages details below)

React-Uploady has a small footprint (by design) with very few (tiny) dependencies.

Bundle Minified size GZipped size
core 29.1KB 10.5KB
core + ui 36.9KB 13.3KB
core + ui + chunked support 44.1KB 15.7KB
everything 71.0KB 22.9KB

Documentation

Getting Started

The best place to get started is at our: React-Uploady Documentation Website

Another great place to learn about React-Uploady is our video series on Youtube.

Changelog

For a list of versions and changes, see the CHANGELOG

Discussions

Please check the discussions area here in Github. If you have a question about use-cases or flows you'd like to achieve with Uploady, discussions is the place to look for existing answers or add your own.

If you're using Uploady in Production, please drop a comment here. It's always great to hear how people and companies use it.

Installation

React-uploady is a mono-repo, and as such provides multiple packages with different functionality.

For React applications, at the very least, you will need the Uploady provider:

#Yarn: 
   $ yarn add @rpldy/uploady

#NPM:
   $ npm i @rpldy/uploady

If you wish to use the uploading mechanism (no UI), at the very least, you will need the Uploader:

#Yarn:
  $ yarn add @rpldy/uploader

#NPM:
  $ npm i @rpldy/uploader

After that, you can add additional packages as needed. See below for more details.

Packages

Main Packages

UI Packages

Providers

Senders

Extras

Internal Packages

Examples

For specific usage, see documentation in the relevant package README file.

For upload options, see the @rpldy/uploady docs.

Simple Upload Button

This example shows how you add Uploady and UploadButton to your app. This is all it takes to get file uploading to work in your React application.

import React from "react";
import Uploady from "@rpldy/uploady";
import UploadButton from "@rpldy/upload-button";

const App = () => (<Uploady
    destination={{ url: "https://my-server/upload" }}>
    <UploadButton/>
</Uploady>);

Custom Upload Button

In case you want to use your own component as the upload trigger, use the asUploadButton HOC:

import React from "react";
import Uploady from "@rpldy/uploady";
import { asUploadButton } from "@rpldy/upload-button";

const DivUploadButton = asUploadButton((props) => {
    return <div {...props} style={{ cursor: "pointer" }}>
        DIV Upload Button
    </div>
});

const App = () => (<Uploady
    destination={{ url: "https://my-server/upload" }}>
    <DivUploadButton/>
</Uploady>);

Progress Hook

import React from "react";
import Uploady, { useItemProgressListener } from "@rpldy/uploady";
import UploadButton from "@rpldy/upload-button";

//must be rendered inside <Uploady>
const LogProgress = () => {
    useItemProgressListener((item) => {
        console.log(`>>>>> (hook) File ${item.file.name} completed: ${item.completed}`);
    });

    return null;
}

const App = () => (<Uploady
    destination={{ url: "https://my-server/upload" }}>
    <LogProgress/>   
    <UploadButton/>
</Uploady>);

Add support for resumable(tus) uploads

 import React from "react";
 import TusUploady from "@rpldy/tus-uploady";
 import UploadButton from "@rpldy/upload-button";
 
 const App = () => (<TusUploady
     destination={{ url: "https://my-tus-server/upload" }}
     chunkSize={2142880}
     sendDataOnCreate>
     <UploadButton/>
 </TusUploady>);

Add support for chunked uploads

Can be used with servers that support chunked uploads

import React from "react";
import ChunkedUploady from "@rpldy/chunked-uploady";
import UploadButton from "@rpldy/upload-button";

const App = () => (<ChunkedUploady
    destination={{ url: "https://my-server/upload" }}
    chunkSize={5242880}>
       
    <UploadButton/>
</ChunkedUploady>);

Find more (advanced) examples in our guides and storybook.

Important Concepts

Upload Options

These are the options that are passed to the uploader to configure aspects of the upload process. For example, whether files can be grouped in a single request (by default, no).

Upload Options are typically passed to the Uploady instance. But these can be overridden. For example, by props passed to the upload button. Or even during upload processing.

Destination

Passed as a part of the upload options. It's an object that is used to configure the end-point where the files will be uploaded to. Its type is defined here.

See more information in the Uploady doc.

At the very least, a destination should contain a URL property with the server endpoint.

Enhancer

(uploader: UploaderType, trigger: Trigger<mixed>) => UploaderType

Enhancers are functions that can enhance an uploader instance. They are also passed as part of the options given to the Uploady instance.

As they are applied when the uploader instance is created, they can change the way uploader does things or pass different defaults.

See this guide for practical information and sample code.

Batch

When a file or files are handed over to the uploader, they are grouped into a batch. This batch will have its own lifetime events. With a batch ID, it is possible to cancel all files that are part of it. It can also be used to retry all files in the batch (see @rpldy/retry).

BatchItem

Each file (or URL) added to the uploader is wrapped by a BatchItem object. They will have a unique ID within the life-time of the uploader instance. A BatchItem has its own lifetime events.

Resumable Uploads

Uploady supports resumable uploads through the tus protocol. Instead of using <Uploady> from @rpldy/uploady, use <TusUploady> from @rpldy/tus-uploady and you will have resumable upload support on the client side. Your server will also have to support the same protocol for this to work, of course.

See the @rpldy/tus-uploady documentation for more details.

UMD Bundles

React-uploady is also available on CDNs such as unpkg.com and jsdelivr.com

See this guide for more information on how to use.

jsDelivr

Bundle URL
core https://cdn.jsdelivr.net/npm/@rpldy/uploader/lib/umd/rpldy-core.umd.min.js
core + ui https://cdn.jsdelivr.net/npm/@rpldy/uploady/lib/umd/rpldy-ui-core.umd.min.js
core + ui + chunked support https://cdn.jsdelivr.net/npm/@rpldy/chunked-uploady/lib/umd/rpldy-ui-core-chunked.umd.min.js
everything https://cdn.jsdelivr.net/npm/@rpldy/uploady/lib/umd/rpldy-all.umd.min.js

You will most likely need the polyfill (core js) bundle as well (load it first):

unpkg

Bundle URL
core https://unpkg.com/@rpldy/uploader/lib/umd/rpldy-core.umd.min.js
core + ui https://unpkg.com/@rpldy/uploady/lib/umd/rpldy-ui-core.umd.min.js
core + ui + chunked support https://unpkg.com/@rpldy/chunked-uploady/lib/umd/rpldy-ui-core-chunked.umd.min.js
everything https://unpkg.com/@rpldy/uploady/lib/umd/rpldy-all.umd.min.js

You will most likely need the polyfill (core js) bundle as well (load it first):

Note that unpkg does a redirect to the latest version in case the URL doesn't already contain it. So don't copy any of the URLs above into your code. Instead, load them in the browser first and then copy the final URL from there (after the redirect).

Contribute

Show Uploady your support by giving us a โญ.

If you'd like to help Uploady grow & improve, take a look at the Contributing doc.

The Discussions page is a great place to ask questions, raise ideas and interact with Uploady maintainer, users and contributors.

Already using Uploady in Production? Let us know how & where in this open discussion.

Financial Contributors

Companies/Organizations that have contributed to the project:

Support us

Want to help sustain and grow Uploady? You can become a financial backer on OpenCollective.

Become a financial contributor and help us sustain our community.

You can make a one-time contribution or on a monthly basis

Or just buy me a coffee ๐Ÿ˜„

Acknowledgements

logo's wing thanks to Illustration Vectors by Vecteezy

react-uploady's People

Contributors

0x111 avatar alexcheuk avatar canrau avatar dependabot[bot] avatar garbles avatar github-actions[bot] avatar kkolstad avatar rickythink avatar yoavniran avatar zgottlieb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-uploady's Issues

tus-uploady: Location not available in uploadResponse on UPLOADER_EVENTS.ITEM_FINISH

Describe the bug
When uploading a file using tus-uploady, the Location is provided by the tus server.
However, on UPLOADER_EVENTS.ITEM_FINISH I seem to be getting the response of the last PATCH:
data: ""
headers:
cache-control: "no-store"
content-length: "0"
content-type: "text/html; charset=utf-8"
tus-res umable: "1.0.0"
upload-offset: "469"
instead of the response of the last POST with the Location information

To Reproduce
Upload a file using the library, and search for the Location header in uploadResponse

Expected behavior
Location header is available

Versions
Specify the versions of the @rpldy packages you're using: 0.6.0
Which browser this bug reproduces in: Chrome 85

Code
const tusEnhancer = getTusEnhancer({
parallel: 1,
});
const random = "asdfqwfwefiqwfpjoqwef"
const uploader = createUploader({
enhancer: tusEnhancer,
autoUpload: true,
grouped: false,
destination: {url: "https:///upload/",
filesParamName: random,
headers: {Authorization: getAuthorization()}
},
params: {
project: "p",
access: "a",
},
sendDataOnCreate: true,
});
uploader.add (file);

Upload button doesn't trigger upload after abort

Here is the reproduce link: https://codesandbox.io/s/rough-lake-5v98z

  1. Start a new upload (with large file so you'll have enough time to click the abort).
  2. Abort the upload with the abort button.
  3. Try to start a new upload.

After choosing a file in the file dialog, the upload process will not start.
As far as I can tell it only happens after abort. If you let the upload process to complete it works fine.

It might be a wrong implementation on my side but I don't think I'm doing anything weird or unusual.

Thanks.

Who's Using and How?

Using Uploady in Production?

Or are you planning to?

Please share your use-case and company (if relevant).
It will be great to know how Uploady is used in the wild ๐Ÿง

Abort event for abortAll?

This is the way i'm using chunked-uploady:

import React, { useState, useCallback } from 'react'
import ChunkedUploady, {
  useBatchStartListener,
  useBatchProgressListener,
  useBatchFinishListener,
  useBatchAbortListener,
  useAbortBatch,
} from '@rpldy/chunked-uploady'
import { asUploadButton } from '@rpldy/upload-button'
import { UploadIcon, StopIcon } from 'components/icons'
import { message, Button, Tooltip, Progress } from 'antd'


const UploadButton = asUploadButton(
  React.forwardRef((props, ref) => {
    const [visible, setVisible] = useState(true)
    useBatchStartListener(() => {
      setVisible(false)
    })

    useBatchAbortListener(() => {
      setVisible(true)
    })

    useBatchFinishListener(() => {
      setVisible(true)
    })

    return (
        {visible ? (
          <Button shape="circle" {...props} ref={ref}>
            <UploadIcon />
          </Button>
        ) : null}
    )
  })
)

const UploadProgress = () => {
  const [visible, setVisible] = useState(false)
  const [currentBatch, setCurrentBatch] = useState('')
  const abortBatch = useAbortBatch()

  const onAbort = useCallback(() => {
    abortBatch(currentBatch)
  }, [abortBatch, currentBatch])

  useBatchStartListener(batch => {
    setCurrentBatch(batch.id)
    setVisible(true)
  })

  const progress = useBatchProgressListener()

  useBatchAbortListener(() => {
     message.error('File upload aborted')
     setVisible(false)
  })

  useBatchFinishListener(() => {
    setVisible(false)
  })

  return visible ? (
    <div>
      <Tooltip title="Abort upload">
        <Button shape="circle" icon={<StopIcon />} onClick={onAbort} />
      </Tooltip>
      <Progress type="circle" percent={parseInt(progress?.completed)} />
    </div>
  ) : null
}

const Upload = () => {
  return (
      <ChunkedUploady destination={{ url: 'api/upload' }}>
        <UploadButton />
        <UploadProgress />
      </ChunkedUploady>
  )
}

export default Upload

As you can see in order to abort the upload i'm forced to maintain a state with the current batch id.
What I really would like is to use the abortAll hook since I really want to cancel everything in this case. But it seems like abortAll doesn't trigger the useBatchAbortListener nor does it have his own abort event...

I Wonder if i'm missing something here or this is a missing feature.

Retry does not work

I try to made retry UI by your example https://react-uploady-storybook.netlify.app/?path=/story/retry-hooks--with-retry-and-preview.

But i got this error after start function retry = useRetry();

I cannot retry item when current batch is not finished.

If i create 3 batch by 1 item in it, retry works perfectly.

index.js:88 Uncaught (in promise) Error: Uploader queue conflict - item batch-1.item-2 already exists (recycled: true)
    at add (index.js:88)
    at Proxy.forEach (<anonymous>)
    at Object.uploadBatch (index.js:104)
    at Object.process (processor.js:23)
    at _callee$ (uploader.js:77)
    at tryCatch (runtime.js:65)
    at Generator.invoke [as _invoke] (runtime.js:303)
    at Generator.prototype.<computed> [as next] (runtime.js:117)
    at asyncGeneratorStep (uploader.js:22)
    at _next (uploader.js:24)

export const PreviewImage = memo((props: any) => {
  const { id, url, name, props:{ className = "", ...rest } = {} } = props;

  const [progress, setProgress] = useState(0);
  const [itemState, setItemState] = useState(0);
  const abortItem = useAbortItem();
  const retry = useRetry();
  const onAbortClick = useCallback(() => abortItem(id), [abortItem, id]);
  const onRetryItem = useCallback(() => retry(id), [retry, id]);

  useItemProgressListener(item => {
    console.log("useItemProgressListener");

    if (item.completed > progress) {
      setProgress(item.completed);
      setItemState(() =>
        item.completed === 100 ? STATES.DONE : STATES.PROGRESS
      );
    }
  }, id);

  useItemAbortListener(() => {
    console.log("useItemAbortListener");

    setItemState(STATES.ABORTED);
  }, id);

  useItemErrorListener(() => {
    console.log("useItemErrorListener");
    setItemState(STATES.ERROR);
  }, id);

  useRetryListener(({ items }) => {
    console.log("##### RETRY EVENT - retrying items: ", items);
  });

  return (
    <div className={cn(styles.previewImage, className, {[styles.hidden]: itemState === STATES.DONE })} {...rest}>
      {
        itemState !== STATES.DONE
          ? <div className={styles.backdrop}>
              {
                itemState === STATES.PROGRESS
                  ? (
                    <>
                      <Circle
                        className={styles.progressbar}
                        strokeWidth={10}
                        trailWidth={10}
                        percent={progress}
                      />
                      <Icon name="cross" onClick={onAbortClick} className={styles.abort}/>
                    </>
                  )
                  : null
              }
              {
                itemState === STATES.ABORTED || itemState === STATES.ERROR
                  ? <Icon name="arrow-circle" onClick={onRetryItem} className={styles.retry}/>
                  : null
              }
            </div>
          : null
      }
      <img src={url} alt={name}/>
    </div>
  )
});

Window is not defined - ssr problem

Trying to use your great package with SSR.
But I got error on server

ReferenceError: window is not defined
    at Object.<anonymous> (/*/node_modules/@rpldy/uploader/lib/utils.js:16:40)

My config
"@rpldy/upload-drop-zone": "^0.5.0",
"@rpldy/uploady": "^0.5.0",

<Uploady
              multiple
              grouped
              maxGroupSize={2}
              method="POST"
              destination={{url: generateApiUrl(API_ROUTES_POST.FILES, {method: "POST"}) }}
            >
              <UploadDropZone
                onDragOverClassName="drag-over"
                grouped={grouped}
                maxGroupSize={groupSize}
              >
                <span>Drag&Drop File(s) Here</span>
              </UploadDropZone>
</Uploady>

Uploady Context upload and abort methods issues

I'm creating an object for the uploadyContext API and trying to simulate events inside the context listener hooks, but neither seems to be working.

  1. having autoUpload = false in the component wrapper and calling uploadyContext.upload(batchId) => fail
  2. having autoUpload = true in the wrapper and calling uplodyContet.abort(itemId) => fail
import {  
  useBatchStartListener,
  useBatchFinishListener,
  useItemStartListener,
  useItemFinishListener,
  useItemProgressListener,
  useBatchAbortListener,
  useBatchCancelledListener,
  useItemAbortListener,
  useItemCancelListener,
  useBatchAddListener,
  useItemErrorListener
, UploadyContext } from '@rpldy/uploady';
import { Batch, BatchItem } from '@rpldy/shared';

// .... Inside my React component ... //

const uploadyContext = React.useContext(UploadyContext);

useBatchAddListener((batch: Batch) => {
   console.warn(`batch ${batch.id} was just added with ${batch.items.length} items`);
    uploadyContext.upload(batch.items[0].batchId); // Calling with the batchId or should be by itemId ?
  });

useItemStartListener((item: BatchItem) => {
    // Cancel the upload if given file already exceeds the maximum files allowed or the size of any       
   console.warn(`item ${item.id} started uploading`);  
    uploadyContext.abort(item.id);
});


useItemProgressListener((item: BatchItem) => {
  console.warn(
      `item ${item.id} File ${item.file.name} is ${item.completed}% done and ${item.loaded} bytes uploaded`
    );

// Despite calling`abort` at the itemStartEvent above, the web socket continues with the upload
});

'asUploadButton' causing React warning

Using asUploadButton like in the example causing the following warning in the console:

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Check the render method of `ForwardRef(AsUploadButton)`.
    in Unknown (created by ForwardRef(AsUploadButton))

Versions
Uploady 0.5.0
React 16.13.1

Code

import React, { useState } from 'react'
import ChunkedUploady, {
  useBatchStartListener,
  useBatchFinishListener
} from '@rpldy/chunked-uploady'
import { asUploadButton } from '@rpldy/upload-button'
import { Button } from 'antd'
import { UploadOutlined } from '@antd-design/icons'

const UploadButton = asUploadButton(props => {
  const [visible, setVisible] = useState(true)

  useBatchStartListener(() => {
    setVisible(false)
  })
  useBatchFinishListener(() => {
    setVisible(true)
  })

  return visible ? (
    <Button shape="circle" {...props}>
      <UploadOutlined />
    </Button>
  ) : null
})

const Upload = (props) => {
  return (
      <ChunkedUploady
        destination={{
          url: props.url
        }}
        multiple={props.multiple}
        withCredentials={true}
        params={props.params}
        accept={props.accept}
      >
        <UploadButton  />
      </ChunkedUploady>
  )
}

export default Upload

TypeError: proxy[key] is null

Hi.. This library is really great.. I like this concept..
But, when I tries to implement it in my next.js app (just copy and paste from your example):

           <Uploady
                debug
                destination={{ url }}
            >
                <UploadButton>Upload Files</UploadButton>
            </Uploady>

I got this error:

TypeError: proxy[key] is null

Any idea about this error?

Abort not working on autoUpload = false OR Who to remove one file from the List?

Describe the bug
When autoUpload is false and abort is called the item will not be removed .

Expected behavior
Abort deletes the file from the list OR a remove method is provided.

Versions
"@rpldy/uploady": "^0.8.3",
"@rpldy/upload-drop-zone": "^0.8.3",
"@rpldy/uploader": "^0.8.3",
"@rpldy/sender": "^0.8.0",
"@rpldy/shared": "^0.8.0",

Code

const FileItems = () => {
  const abort = useItemAbort();
  const [files, setFiles] = useState([]);
  useBatchAddListener((batch: Batch) => {
    setFiles(prevState => [...prevState, ...batch.items]);
  });

  useItemAbortListener((batch: BatchItem) => {
    debugger;
  });

  useBatchAbortListener(batch => {
    debugger;
  });

  useAllAbortListener(() => {
    debugger;
  });

  return files.map(file => <FileItem file={file} onClick={() => abort(file.id)} />)
}

const App = () => {
  return <Uploady autoUpload={false} >
      <FileItems />  
   </Uploady
}

tus-uploady: Support destination headers & clarify readme

I noticed while trying to implement this package that the tus-uploady readme states:

# packages/ui/tus-uploady/README.md L63
It also supports the Upload-Metadata header and will turn the destination params prop into the metadata key/value.

Headers aren't passed through with the prop destination={{url: "https://my-server", headers: {"x-custom": "123"}}} even though the Readme states all UploadOptions props can be passed to TusUploady.

I would suggest either allowing custom headers or updating the Readme to make the params object more clear in the props table.

I'd also suggest making it clear that you don't have to pre-encode the Upload-Metadata values in Base64 as is required in the TUS Docs concerning the Upload-Metadata format. The destination params: {key: 'value'} is automatically converted to Upload-Metadata: key dmFsdWU=.

The `accept` parameter is ignored when dragging and dropping files.

Describe the bug
The accept parameter is ignored when dragging and dropping files. For example, when set to accept="image/*", non-image file types cannot get uploaded from the UploadButton but they are uploaded when dragging and dropping.

To Reproduce
Steps to reproduce the behavior:

  1. If you click the UploadButton in the provided codesandbox and the native file browser will appear. For me, using Chrome 85 on Mac Mojave, all non-image file types appear greyed out and cannot be selected.
  2. Open the Network tab in the dev tools
  3. Drag a non-image file into the UploadDropZone (I used a .mov type)
  4. A network request is triggered to upload the file

Expected behavior
Only file types that are listed in the accept parameter can be uploaded. In this case, a non-image would not trigger a network request, and there would be some kind of error response from Uploady.

Versions
"@rpldy/upload-button": "0.7.0",
"@rpldy/upload-drop-zone": "0.7.0",
"@rpldy/uploady": "0.7.0"

Code
https://codesandbox.io/s/uploady-example-55600

Hide upload Button

Can i hide upload Button when Previews count is = 5?

return (
    <Uploady
      debug
      destination={destination}
      concurrent={concurrent}
      multiple={multiple}
      {...rest}
    >
      <div className={styles.uploadedImagesWrp}>
        <UploadPreview        />

          { 
          previews && previews.length < 5
             ? <UploadButton className={styles.uploader}/>
             : null 
           }
      </div>
    </Uploady>
  )

Where can i get previews?

Chunked Uploady does not support UploadButton

I am using chunked upload feature but getting error Invariant Violation: Uploady - valid UploadyContext not found. Make sure you render inside .

I have resolved above error with to import chunkedUploady through "@rpldy/uploady".

I have gone through the code and found that uploady is returning from chunkeduploady, so why i am getting this error.

Now chunkedSize and chunked are not supported by chunkeduploady.

Here is my code...

import ChunkedUploady from "@rpldy/uploady";
import { useContext } from 'react';

import { UploadyContext } from '@rpldy/uploady';

const UploadContent = () => {
return (
< ChunkedUploady
chunkSize={2142880}
chunked={true} >

        < UploadButton1 />

< /ChunkedUploady>);

}
export default UploadContent;

const UploadButton1 = () => {
const uploady = useContext(UploadyContext);
let url = null;

const onClick = async () => {
    try {
        if (!url) {
            await apiGetSignedUploadUrl(idType)
                .then((out) => {
                    const { success, data } = out;
                    if (success) {
                        url = data.uploadUrl;

                    }
                })
        }
        uploady.showFileUpload({
            destination: {
                url,
                method: 'PUT',
                headers: {
                    "Content-Type": '',
                },
            },

            sendWithFormData: false,
        });

    } catch (error) {
        console.error(error, error.response);
        throw error;
    }
}

return <>
    <Button type='button'
        onClick={onClick}
        style={{
            border: isError ? '1px solid red' : '1px solid rgba(166, 125, 255, 0.5)',
            color: isError ? 'red' : '#a67dff'
        }}
    >
        {getUrl ? successCaption : 'Upload'}</Button>
    <div>
        <span style={{ color: isError ? 'red' : '#a67dff' }}>{isError ? errMsg : ''}</span>
    </div>
</>

}


Thanks in advance!!

Invalid Package Config when added via yarn and imported

Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /Users/lucamarchal/code/ProvePay/node_modules/@rpldy/uploady/package.json. "exports" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.

Upload fails with a 0-byte file.

Describe the bug
When I try to upload a 0-byte file, I get the following error:

Uncaught (in promise) ChunkedSendError: start byte 0 is invalid. File size: 0

To Reproduce
Steps to reproduce the behavior:

  1. Install
    "@rpldy/tus-uploady": "^0.7.0",
    "@rpldy/uploader": "^0.7.0",
    "@rpldy/uploady": "^0.7.0",
  2. Use code such as
    const uploader = createUploader({
    enhancer: tusEnhancer,
    autoUpload: true,
    grouped: false,
    destination: {url: config.url.datasetTus,
    headers: {Authorization: getAuthorization()}
    },
    sendDataOnCreate: true,
    });
  3. Check the console for Uncaught (in promise) ChunkedSendError: start byte 0 is invalid. File size: 0
    Expected behavior
    Correct upload of the 0-size file.

Versions
Specify the versions of the @rpldy packages you're using.
"@rpldy/tus-uploady": "^0.7.0",
"@rpldy/uploader": "^0.7.0",
"@rpldy/uploady": "^0.7.0",

Google chrome: Version 85.0.4183.121 (Offizieller Build) (32-Bit)

Nextjs: ReferenceError: regeneratorRuntime is not defined

Keep getting this error, i have 'babel/next' in my babelrc file.

ReferenceError: regeneratorRuntime is not defined at /Users/m5/projects/meet_apps/pwa/node_modules/@rpldy/uploader/lib/queue/batchHelpers.js:104:46 at Object.<anonymous> (/Users/m5/projects/meet_apps/pwa/node_modules/@rpldy/uploader/lib/queue/batchHelpers.js:136:2) at Module._compile (internal/modules/cjs/loader.js:1138:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10) at Module.load (internal/modules/cjs/loader.js:986:32) at Function.Module._load (internal/modules/cjs/loader.js:879:14) at Module.require (internal/modules/cjs/loader.js:1026:19) at require (internal/modules/cjs/helpers.js:72:18) at Object.<anonymous> (/Users/m5/projects/meet_apps/pwa/node_modules/@rpldy/uploader/lib/queue/processFinishedRequest.js:12:21) at Module._compile (internal/modules/cjs/loader.js:1138:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10) at Module.load (internal/modules/cjs/loader.js:986:32) at Function.Module._load (internal/modules/cjs/loader.js:879:14) at Module.require (internal/modules/cjs/loader.js:1026:19) at require (internal/modules/cjs/helpers.js:72:18) at Object.<anonymous> (/Users/m5/projects/meet_apps/pwa/node_modules/@rpldy/uploader/lib/queue/processBatchItems.js:12:54)

not sure what other information to provide as i can't get past the example with custom button in my Nextjs app

Form data ordering

Hi,

Some services like S3 stop reading form data once the 'file' value has been reached.
When looking at the uploady POST request, it starts with the 'file' value, and so the other values like 'key' that are needed for S3, are ignored.

Is there any way in which the order of values for the POST can be changed so that 'file' comes last?

modifying inputFieldName prop does not reflect in formData

Describe the bug
I'm not sure if I am doing this right or if this is a bug, but I have been trying to modify the default inputFieldName prop from "file" to a custom name, say "myCustomField" so that on submission/upload the field name of the file in formData will be "myCustomField". However, even after modifying the inputFieldName prop on the Uploady component, the field retains the "file" input field name. (P.S I am using a custom component as upload button, even though I think this shouldn't matter)

To Reproduce

const CustomUploader = ({useMock, fieldName}) => {
  const [isUploading, setIsUploading] = useState(false);
  const [uploadStatus, setUploadStatus] = useState("");

  const onUploading = (value) => setIsUploading(value);
  const handleUploadStatus = (value) => setUploadStatus(value);

  const extraProps={onUploading, handleUploadStatus};

  return (
    <Uploady
      destination={{ url: "http://localhost:5000/v1/mock-path" }}
      autoUpload={false}
      enhancer={useMock ? mockEnhancer : null}
      inputFieldName={fieldName}
    >
      <div className="Uploader">
        <Custombutton { ...{extraProps} }/>
        <UploadProgress animated={isUploading} status={uploadStatus}/>
      </div>
    </Uploady>  
  )
}

const mockEnhancer = (uploader) => {
  const mockSender = createMockSender({ delay: 5000 });
  uploader.update({ send: mockSender.send });
  return uploader;
};

---------------------------------------------------------
Used in another component as:

<CustomUploader fieldName="myCustomField" />

Below is a sample formData request on upload

XHRPOSThttp://localhost:5000/v1/mock-path
    Content-Disposition: form-data; name="file"; filename="Text.txt"
    Content-Type: text/plain
    Some Text File

Expected behavior
Expected the request to be as shown below

XHRPOSThttp://localhost:5000/v1/mock-path
    Content-Disposition: form-data; name="myCustomField"; filename="Text.txt"
    Content-Type: text/plain
    Some Text File

Versions
Specify the versions of the @rpldy packages you're using.

    "@rpldy/mock-sender": "^0.8.2",
    "@rpldy/upload-button": "^0.8.2",
    "@rpldy/uploady": "^0.8.2",

Which browser this bug reproduces in.
Firefox 81

Code
Please provide code sample or better yet, a link to a reproducing repository or best yet, codesandbox (fiddle, etc) where issue can be reproduced easily

Server side error: "ReferenceError: File is not defined"

Describe the bug
When using Uploady in a SSR app, it throws this error on the server side. "ReferenceError: File is not defined"

To Reproduce

  • Install NextJS (I assume just using this next create app would be the quickest way https://nextjs.org/docs/api-reference/create-next-app ).
  • Install npm i @rpldy/uploady
  • Create a file in next pages/test.js and use the code provided below
  • Start dev server, navigate to the /test page

Expected behavior
Does not throw an error.

Versions
I'm still using version 9.5.2 though of NextJS, their latest release is 10.0.3 and latest on the 9.5.* branch is 9.5.5. Have not had the chance to update yet.

"@rpldy/uploady": "^0.8.0",
"react": "16.13.1",
"react-dom": "16.13.1",
"next": "9.5.2",

Code

This is what I put in the test.js file:

import Uploady from '@rpldy/uploady'

export default function TestPage() {
  return (
      <Uploady destination={{ url: '/path/to/upload' }}>
        Hello
      </Uploady>
  )
}

Stack Trace I get:

ReferenceError: File is not defined
    at isNativeFile (<working dir>/node_modules/@rpldy/simple-state/lib/cjs/utils.js:20:25)
    at isProxiable (<working dir>/node_modules/@rpldy/simple-state/lib/cjs/utils.js:24:68)
    at deepProxy (<working dir>/node_modules/@rpldy/simple-state/lib/cjs/createState.js:40:30)
    at _default (<working dir>/node_modules/@rpldy/simple-state/lib/cjs/createState.js:112:46)
    at createUploaderQueue (<working dir>/node_modules/@rpldy/uploader/lib/cjs/queue/uploaderQueue.js:41:50)
    at _default (<working dir>/node_modules/@rpldy/uploader/lib/cjs/processor.js:18:37)
    at _default (<working dir>/node_modules/@rpldy/uploader/lib/cjs/uploader.js:166:45)
    at <working dir>/node_modules/@rpldy/shared-ui/lib/cjs/useUploader.js:33:37
    at Object.useMemo (<working dir>/node_modules/react-dom/cjs/react-dom-server.node.development.js:1239:19)
    at useMemo (<working dir>/node_modules/react/cjs/react.development.js:1521:21)

And just tagging the prior comments on this issue for anyone that might be googling: #76

Adding new files via context.upload(file) doesn't always trigger uploading

When calling context.upload(file), it randomly seems to not trigger the upload process. autoUpload is set to true.

Trying to force a uploadyContext.processPending() doesn't do anything either.

UPLOADER_EVENTS.BATCH_ADD is successfully called with the correct file though.
Uploadhandler's useRequestPreSend is not called.

Following code is used:
<Uploady> <UploadHandler /> <UploadButton className="btn btn-primary"> Upload Files </UploadButton> </Uploady>

Any ideas where I could look?

Begin upload on form onSubmit

Hi again!

I'm having trouble parsing how to use autoUpload={false} in conjunction with form values.

I have a requirement to use the TUS protocol for uploading videos. The form has fields which populate the Upload-Metadata (params) values and they need to be set before the upload begins. (implementing that part isn't a problem, see screenshot for context)

I've crawled through the docs and packages to find the best path forward using uploady (without scrapping third-party packages and doing it all manually, of which i'd like to avoid) but I need a push in the right direction -- plus this could potentially be a good storybook example, telling uploady to "start uploading now" and clearing up how to do that, because I wont be the only one who will be looking for it.

image

Pending and Concurent Upload: Upload of Items is Triggered several Times

Describe the bug
When Uplody is created with autoUpload = false and concurrent = true, upload of Items is triggered several Times.

To Reproduce
See this Sandbox: https://codesandbox.io/s/vibrant-cdn-b25h6?fontsize=14&hidenavigation=1&theme=dark&file=/src/App.js

  1. Choose 2 files at once. Click Upload: in the console you can see "batch-1.item-2 Uploading" was logged 2 Times
  2. Choose 2 files, one after another. Click Upload: Both "batch-1.item-1" and "batch-2.item2" was logged 2 Times + An Type Error occured.
  3. Choose 4 files, two after another two. Click Upload: "batch-1.item-1" x2; "batch-1.item-2" x 3; "batch-2.item-3" x 6; "batch-2.item-4" x 6

In production i Noticed this behavior in the Network-tab.

Expected behavior
Each file only triggered once.

Versions
@rpldy/uplody 0.8.3
@rpldy/uploder 0.8.3
@rpldy/sender 0.8.0

Which browser this bug reproduces in.
Tested in Chrome

Code
See sandbox above. I wrapped the "send"-method for logging purposes.

Resetting state

What is the recommended way to reset the uploader. I.e. a user has uploaded a bunch of items, and they want to clear the finished batch(es) and start afresh. I guess I could trigger a complete remount of the component somehow.

Unexpected deletion of uploading images when trying to retry

I abort and retry items in batch of 7 items, and got this error

batchHelpers.js:13 Uncaught (in promise) TypeError: Cannot read property 'batch' of undefined
    at getBatchFromState (batchHelpers.js:13)
    at triggerUploaderBatchEvent (batchHelpers.js:106)
    at cleanUpFinishedBatch (batchHelpers.js:98)
    at processFinishedRequest.js:65
    at processBatchItems.js:94

And all my not uploaded items is disappeared!

Steps to reproduce:

  1. Slow network speed
  2. Upload 10 items in 1 batch on multiply
  3. Abort and retry all of items step by step
  4. Wait then about 20% of items will be uploaded
  5. Items disappeared and you got error

move immer to dev deps

check if it doesnt cause build issues
because immer isnt actually used in build it should be possibe to move to deps so its not counted by bundlephobia

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.