使用动态文件名的 react-fine-uploader S3 上传

react-fine-uploader S3 upload using dynamic filename

背景

我正在集成使用 react-fine-uploader 创建一个 React 应用程序以直接上传到 S3 存储桶,我没有任何服务器端代码。我已经能够使用 react-fine-uploader 开箱即用的常规 uuid 上传到我的存储桶。我现在想做的是动态创建文件名,以便我可以将文件写入 s3 "folders".

问题

我知道我可以配置我的 uploader.options.objectProperties.key,并向它传递一个函数,例如:

var uploader = new qq.s3.FineUploader({
    // ...
    objectProperties: {
        key: function(fileId) {
            return 'folder/within/bucket/' + this.getUuid(fileId);
        }
    }
});

(摘自another answer

当您想要处理可以从 file/uploader 获取的值(例如 uuid)以及其他静态信息时,这很好。我想要的是包含一个从其他地方传递给该组件的文件夹名称。到目前为止,这是我的尝试:

//imports...
const uploader = new FineUploaderS3({
    options: {
        //other options...
        objectProperties: {
            key: function(fileId) {
                return folderName + '/' + this.getUuid(fileId);
            }
        }
    }
});

var folderName = null;

class FileUpload extends Component {
    constructor(props) {
        super(props);

        folderName = this.props.folderName;
    }

    render() {

        return (
            <div>
                <Gallery uploader={uploader} />
            </div>
        );
    }
};

export default FileUpload;

目前这会将其添加到 s3 中名为 "null" 的文件夹中,但我已成功将此组件传递给 props 中的 folderName。

我需要做什么来连接这些东西?

最初呈现 FileUpload 时,fileUpload 属性的值是多少?如所写,这只会在 FineUploaderS3 实例最初呈现组件时可以访问的范围内设置 fileUpload 变量。如果稍后给 fileUpload 属性赋值,您可能需要在发生这种情况时使用 componentWillReceiveProps() 来更新 folderName(并且您只能有一个 FileUpload 组件,因为最后渲染的将获胜)。


另一种方法是创建依赖于组件的 props 或状态的对象作为其生命周期的一部分,并将它们存储在组件实例本身上,例如:

class FileUploadComponent extends Component {
  constructor(props) {
    super(props)
    // We can't use an arrow function for the key function below as we need to
    // access both this component's props and the FileUploader instance within it
    let component = this
    this.uploader = new qq.s3.FineUploader({
      // ...
      objectProperties: {
        key(fileId) {
          return `${component.props.folderName}/${this.getUuid(fileId)}`
        }
      }
    })
  }

  render() {
    return <div>
      <Gallery uploader={this.uploader}/>
    </div>
  }
}