如何使用带有 antd 上传功能的 CustomRequest 将图片上传到 Firebase?

Posted

技术标签:

【中文标题】如何使用带有 antd 上传功能的 CustomRequest 将图片上传到 Firebase?【英文标题】:How to use CustomRequest with antd upload function to upload images to firebase? 【发布时间】:2019-11-22 17:26:15 【问题描述】:

我正在尝试使用 antd 上传组件和 pictures wall 示例将图像上传到我的 Firebase 存储。

最初我尝试使用操作属性as out lined here 得到相同的结果。然后,我尝试使用该问题的解决方案中概述的 customRequest 表单。在挣扎了一整天之后,我似乎无法让它工作。显然我不太明白发生了什么。

我的各种变化功能..

  handleCancel = () => this.setState( previewVisible: false );

  handlePreview = async file => 
    if (!file.url && !file.preview) 
      file.preview = await getBase64(file.originFileObj);
    

    this.setState(
      previewImage: file.url || file.preview,
      previewVisible: true,
    );
  ;

  handleChange = (info) => 
    console.log('handleChange',info);
    if (info.file.status === 'uploading') 
      console.log('setting loading to true');
      this.setState( loading: true );
      return;
    
    if (info.file.status === 'done') 
      console.log('setting loading to false');
      getBase64(info.file.originFileObj, imageUrl => this.setState(
        imageUrl,
        loading: false
      ));
    
  ;

我的自定义上传功能..

  customUpload = async ( onError, onSuccess, file ) => 
    console.log("customUpload called");
    console.log(file);
    const storage = firebase.storage();
    const metadata = 
        contentType: 'image/jpeg'
    ;
    const storageRef = await storage.ref();
    // const imageName = generateHashName() //a unique name for the image
    const imgFile = storageRef.child(`Property Photos/$file.png`);
    try 
      const image = await imgFile.put(file, metadata);
      onSuccess(null, image);
    
    catch(e) 
       onError(e);
    ;
  ;

我的渲染 JSX..

<Form.Item label="Photos">
  <div className="clearfix">
    <Upload
      listType="picture-card"
      fileList=fileList
      multiple=true
      accept="image"
      onPreview=this.handlePreview
      onChange=this.handleChange
      customRequest=this.customUpload
    >
      this.imageUrl ? <img src=this.imageUrl  /> : uploadButton
    </Upload>
    <Modal visible=previewVisible footer=null onCancel=this.handleCancel>
      <img  style= width: '100%'  src=previewImage />
    </Modal>
  </div>
</Form.Item>

它运行起来很有趣,但似乎有三个问题..

    当我上传图片时,卡片/盒子会永远显示“上传”和动画旋转轮。它永远不会完成并显示图像缩略图。 在选择多个图像时,似乎只有第一个最终会出现在 Firebase 上。再也没有.. 在选择要上载和单击确定的图像时,很长的暂停(5秒?),如应用程序挂起,然后再次单击任何内容。不知道为什么会这样。

感觉就像我只是不明白如何使用这个 customRequest 属性..

【问题讨论】:

【参考方案1】:

一般情况下,需要做的是:将antd Upload的“onProgress”、“onSuccess”和“onError”回调函数连接到cloudStorage上传函数对应的事件观察者上。

https://firebase.google.com/docs/storage/web/upload-files#monitor_upload_progress

所以,customRequest 函数可以是:

let customRequest = (
    file,
    onSuccess,
    onError,
    onProgress,
) => 
    var uploadTask = storageRef.child(`images/$file.name`).put(file);

    // Register three observers:
    // 1. 'state_changed' observer, called any time the state changes
    // 2. Error observer, called on failure
    // 3. Completion observer, called on successful completion
    uploadTask.on(
        "state_changed",
        function (snapshot) 
            // Observe state change events such as progress, pause, and resume
            // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
            var progress =
                (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
            console.log("Upload is " + progress + "% done");

            // CONNECT ON PROGRESS
            onProgress(progress)

            switch (snapshot.state) 
                case firebase.storage.TaskState.PAUSED: // or 'paused'
                    console.log("Upload is paused");
                    break;
                case firebase.storage.TaskState.RUNNING: // or 'running'
                    console.log("Upload is running");
                    break;
            
        ,
        function (error) 
            // Handle unsuccessful uploads

            // CONNECT ON ERROR
            onError(error)
        ,
        function () 
            // Handle successful uploads on complete
            // For instance, get the download URL: https://firebasestorage.googleapis.com/...
            uploadTask.snapshot.ref
                .getDownloadURL()
                .then(function (downloadURL) 
                    console.log("File available at", downloadURL);
 
                    // CONNECT ON SUCCESS
                    onSuccess(downloadURL)  // Pass any parameter you would like
                );
        
    );
;

【讨论】:

看起来我是选择一个还是多个他们上传到firebase的文件,这很好。但是 antd 没有显示缩略图,我注意到我的 handlechange 函数仅在 info.file.status 为“上传”时才被调用。当 info.file.status 完成时,它永远不会被第二次调用。似乎 antd 并没有注意到文件已成功上传的事实,即使调用了 onsuccess,正如我看到“文件可用”的 console.log 以及 downloadURL 所证明的那样。 我是否应该在这里做更多的事情,以便 antd 知道文件已上传,handlechange 被调用,并且我看到 hte 上传图像的缩略图?好像我还缺少什么。

以上是关于如何使用带有 antd 上传功能的 CustomRequest 将图片上传到 Firebase?的主要内容,如果未能解决你的问题,请参考以下文章

vue + antd-vue + 腾讯云点播 完成视频上传功能

Antd的Upload组件上传文件控制文件数量格式等,以及提交时如何获取文件

Antd的Upload组件上传文件控制文件数量格式等,以及提交时如何获取文件

React+Antd+Antd-Img-Crop实现上传固定大小的裁剪头像或者图片(且可控制图片数量)

AntD框架的upload组件上传图片时使用customRequest方法自定义上传行为

使用 customRequest Ant Design (antd) 上传文件停留在“上传”状态