founderlab / react-dropzone-s3-uploader

Drag and drop s3 file uploader via react-dropzone + react-s3-uploader
MIT License
161 stars 82 forks source link

Uploaded File Path #14

Closed talbenbasat closed 7 years ago

talbenbasat commented 7 years ago

Hi,

I'm thinking of using the library but I cant understand how to get the uploaded file path in s3 after the uploading.

I've tested it a little and the onFinish action is triggered with the signingUrl.

Can you please help?

gwilymhumphreys commented 7 years ago

Hey mate, the onFinish callback is given an object {filename, publicUrl, signedUrl}. If it's not, can you check that you have the latest version (0.8.x) and that you don't have another version of react-s3-uploader floating around?

If you're looking for the full s3 url of a file, it's just ${s3Url}/${filename}, where s3Url is your base s3 url that you give to the uploader (e.g. https://mybucket.s3.amazonaws.com).

talbenbasat commented 7 years ago

Hi,

these are the relevant versions:

     "react-dropzone-s3-uploader": "^0.8.0",
    "react-s3-uploader": "^3.3.0",

this is my component:

class FormDropzone extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      files: [],
    };
    this.onFinish = this.onFinish.bind(this);
  }

  onFinish(acceptedFiles, rejectedFiles) {
    this.props.input.onChange(acceptedFiles);

    this.setState({
      files: acceptedFiles,
    });
  }

  onOpenClick() {
    this.dropzone.open();
  }

  render() {
    const { name, accept, multiple, maxSize, meta, ...props } = this.props;

    let touched;
    let error;

    if (meta) {
      touched = meta.touched;
      error = meta.error;
    }

    return (
      <div>
        <DropzoneS3Uploader
          ref={(node) => { this.dropzone = node; }}
          multiple={multiple}
          accept={accept}
          name={name}
          maxFileSize={maxSize}
          server='http://localhost:3000/'
          signingUrl='api/s3_signing_url'
          s3Url='https://bar.s3.amazonaws.com'
          onFinish={this.onFinish}
          className={`${styles.dropzone} ${(touched && error) ? styles.dropzoneError : null}`}
        >
          <div
            style={{ backgroundImage: `url(${this.state.files.length > 0 ? this.state.files[0].preview : defaultImage})` }}
            className={styles.previewImage}
          >
          </div>
        </DropzoneS3Uploader>
      </div>
    );
  }
}

and the way i'm calling it is using redux-form by

          <Field
            name="cover_picture"
            component={FormDropzone}
          />

my signing url is generated using django


def s3_signing_url(request):
    conn = boto.connect_s3()

    object_name = request.GET.get('objectName')
    content_type = mimetypes.guess_type(object_name)[0]

    signed_url = conn.generate_url(
        3000,
        "PUT",
        AWS_STORAGE_BUCKET_NAME,
       object_name,
        headers={'Content-Type': content_type, 'x-amz-acl': 'public-read'})

    return HttpResponse(json.dumps({'signedUrl': signed_url}))

Any idea?

gwilymhumphreys commented 7 years ago

Okay, looks cool. I'm doing something similar with redux form. Your onFinish function should look like this:

  onFinish(info) {
    // info should contain {filename, publicUrl, signedUrl}
    this.props.input.onChange(info.filename);
  }

You can then get the filename from the form value when in render():

  render() {
    const filename = this.props.input.value
    const fileUrl = `https://bar.s3.amazonaws.com/${filename}`
    ... 
  }

Also you have react-s3-uploader@^3.3.0, while this lib is stuck on ^1.2.1. I don't think that's the problem though. Let me know what you're getting passed in onFinish if it's not what we're expecting.

talbenbasat commented 7 years ago

@gwilymhumphreys will do Thanks

talbenbasat commented 7 years ago

Hi @gwilymhumphreys , My result contains the accepted files and the rejected files. while the accepted file has only the upload url to the uploaded file in 3.3.0.

in the 1.2.1 the result is the same.

can you please check?

The boilerplate im using is https://github.com/mxstbr/react-boilerplate/

Tal

talbenbasat commented 7 years ago

this looks relevant - https://github.com/odysseyscience/react-s3-uploader/issues/68 It seems like the prefix should be known by the server and the client only provides the name

talbenbasat commented 7 years ago

btw this will do the job:

 onFinish(uploadedFiles) {
    const regex = /:443([a-zA-Z0-9_.\/]*)\?Signature/g;
    const match = regex.exec(uploadedFiles.signedUrl);

    this.props.input.onChange(match[1]);
  }