npm package: @rc-utils/h5-file
Description: ## 安装
Latest version: 1.0.3-rc.1

# @rc-utils/h5-file

## 安装

使用 npm:

```bash
$ npm i -g npm
$ npm i @rc-utils/h5-file
```

## 使用方法

> 直接引用 `import * as h5FileUtils from '@rc-utils/h5-file'`

### `File` | `Blob` | `Base64` 之间互相转化

```tsx
import {
  convertBase64ToBlob,
  convertBase64ToFile,
  convertBlobToBase64,
  convertBlobToFile,
  convertFileToBase64,
  convertFileToBlob,
} from '@rc-utils/h5-file'
import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const App = () => {
  const [file, setFile] = useState<File>()

  return (
    <div className="container">
      <div className="toolbar">
        <button
          onClick={() => {
            if (file) {
              convertFileToBlob(file).then((blob) => {
                console.log('convertFileToBlob ~ blob', blob)
              })
            } else {
              alert('请先选择文件')
            }
          }}
        >
          File 转 Blob
        </button>
        <button
          onClick={() => {
            if (file) {
              convertFileToBase64(file).then((base64) => {
                console.log('convertFileToBase64 ~ base64', base64)
                console.log('base64.length', (base64 as string).length)
              })
            } else {
              alert('请先选择文件')
            }
          }}
        >
          File 转 Base64
        </button>
        <button
          onClick={() => {
            if (file) {
              convertFileToBlob(file).then((blob) => {
                console.log('预转化:convertFileToBlob ~ blob', blob)
                convertBlobToFile(blob, file.name).then((file) => {
                  console.log('convertBlobToFile ~ file', file)
                })
              })
            } else {
              alert('请先选择文件')
            }
          }}
        >
          Blob 转 File
        </button>
        <button
          onClick={() => {
            if (file) {
              convertFileToBlob(file).then((blob) => {
                console.log('预转化:convertFileToBlob ~ blob', blob)
                convertBlobToBase64(blob).then((base64) => {
                  console.log('convertBlobToBase64 ~ base64', base64)
                  console.log('base64.length', (base64 as string).length)
                })
              })
            } else {
              alert('请先选择文件')
            }
          }}
        >
          Blob 转 Base64
        </button>
        <button
          onClick={() => {
            if (file) {
              convertFileToBase64(file).then((base64) => {
                console.log('预转化:convertFileToBase64 ~ base64', base64)
                convertBase64ToBlob(base64).then((blob) => {
                  console.log('convertBase64ToBlob ~ blob', blob)
                })
              })
            } else {
              alert('请先选择文件')
            }
          }}
        >
          Base64 转 Blob
        </button>
        <button
          onClick={() => {
            if (file) {
              convertFileToBase64(file).then((base64) => {
                console.log('预转化:convertFileToBase64 ~ base64', base64)
                convertBase64ToFile(base64, file.name).then((file) => {
                  console.log('convertBase64ToFile ~ file', file)
                })
              })
            } else {
              alert('请先选择文件')
            }
          }}
        >
          Base64 转 File
        </button>
      </div>
      <div className="main">
        <input
          id="input"
          type="file"
          onChange={(e) => {
            console.log(e)
            const files = e?.target?.files
            setFile(files?.[0])
          }}
        />
      </div>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))
```

### 文件 URL 下载转存为 `File` | `Blob` 对象

```tsx
import { convertURLToBlob, convertURLToFile } from '@rc-utils/h5-file'
import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const demoImageFile = {
  url: '/demos/demo-png.png',
  type: 'image/png',
}

const demoAudioFile = {
  url: '/demos/demo-wav.wav',
  type: 'audio/wav',
}

const demoVideoFile = {
  url: '/demos/demo-ogv.ogv',
  type: 'video/ogv',
}

const App = () => {
  const [imgFile, setImgFile] = useState<Partial<{
    url: string
    name: string
    loading: boolean
  }> | null>(null)
  const [audioFile, setAudioFile] = useState<Partial<{
    url: string
    name: string
    loading: boolean
  }> | null>(null)
  const [videoFile, setVideoFile] = useState<Partial<{
    url: string
    name: string
    loading: boolean
  }> | null>(null)

  return (
    <div className="container">
      <div className="card">
        <div className="main">
          <div className="item">
            <div className="main-label">转化图片展示</div>
            <div className="main-content">
              <img src={imgFile?.url} width="100px" height="100px" />
            </div>
          </div>
          <div className="item">
            <div className="main-label">文件名称</div>
            <div className="main-content">
              {imgFile?.loading ? (
                <div className="loading-text">图片下载转化中...</div>
              ) : (
                <div>{imgFile?.name}</div>
              )}
            </div>
          </div>
          <div className="item">
            <div className="main-label">源文件地址</div>
            <div className="main-content">
              <div>{demoImageFile.url}</div>
            </div>
          </div>
          <div className="item">
            <div className="main-label">转化文件地址</div>
            <div className="main-content">
              <div>{imgFile?.url}</div>
            </div>
          </div>
        </div>
        <div className="toolbar">
          <button
            onClick={() => {
              setImgFile({
                loading: true,
              })
              convertURLToBlob(demoImageFile.url)
                .then((blob) => {
                  console.log('convertURLToBlob ~ blob', blob)
                  const fileUrl = URL.createObjectURL(blob)
                  console.log('convertURLToBlob fileUrl', fileUrl)
                  setImgFile({
                    url: fileUrl,
                    name: 'Blob图片',
                    loading: false,
                  })
                })
                .catch((ex) => {
                  console.log('convertURLToBlob ~ ex', ex)
                  setImgFile({
                    name: '图片转化异常',
                    loading: false,
                  })
                })
            }}
          >
            在线文件URL 转 Blob
          </button>
          <button
            onClick={() => {
              setImgFile({
                loading: true,
              })
              convertURLToFile(demoImageFile.url, {
                fileName: '测试图片',
                fileType: demoImageFile.type,
              })
                .then((file) => {
                  console.log('convertURLToFile ~ file', file)
                  const fileUrl = URL.createObjectURL(file)
                  console.log('convertURLToFile fileUrl', fileUrl)
                  setImgFile({
                    url: fileUrl,
                    name: file.name,
                    loading: false,
                  })
                })
                .catch((ex) => {
                  console.log('convertURLToFile ~ ex', ex)
                  setImgFile({
                    name: '图片转化异常',
                    loading: false,
                  })
                })
            }}
          >
            在线文件URL 转 File
          </button>
        </div>
      </div>
      <div className="card">
        <div className="main">
          <div className="item">
            <div className="main-label">转化音频展示</div>
            <div className="main-content">
              <audio
                src={audioFile?.url}
                controls
                preload="metadata"
                autoPlay={false}
              >
                您的浏览器不支持audio标签。
              </audio>
            </div>
          </div>
          <div className="item">
            <div className="main-label">文件名称</div>
            <div className="main-content">
              {audioFile?.loading ? (
                <div className="loading-text">音频下载转化中...</div>
              ) : (
                <div>{audioFile?.name}</div>
              )}
            </div>
          </div>
          <div className="item">
            <div className="main-label">源文件地址</div>
            <div className="main-content">
              <div>{demoAudioFile.url}</div>
            </div>
          </div>
          <div className="item">
            <div className="main-label">转化文件地址</div>
            <div className="main-content">
              <div>{audioFile?.url}</div>
            </div>
          </div>
        </div>
        <div className="toolbar">
          <button
            onClick={() => {
              setAudioFile({
                loading: true,
              })
              convertURLToBlob(demoAudioFile.url, {
                // 跨域配置
                // responseHeaders: {
                //   'Access-Control-Allow-Origin': '*',
                //   'Access-Control-Allow-Methods': 'OPTIONS, GET, PUT, POST, DELETE',
                //   'Access-Control-Allow-Headers': '*',
                // }
              })
                .then((blob) => {
                  console.log('convertURLToBlob ~ blob', blob)
                  const fileUrl = URL.createObjectURL(blob)
                  console.log('convertURLToBlob fileUrl', fileUrl)
                  setAudioFile({
                    url: fileUrl,
                    name: 'Blob音频',
                    loading: false,
                  })
                })
                .catch((ex) => {
                  console.log('convertURLToBlob ~ ex', ex)
                  setAudioFile({
                    name: '音频转化异常',
                    loading: false,
                  })
                })
            }}
          >
            在线文件URL 转 Blob
          </button>
          <button
            onClick={() => {
              setAudioFile({
                loading: true,
              })
              convertURLToFile(demoAudioFile.url, {
                fileName: '演示音频文件',
                fileType: demoAudioFile.type,
              })
                .then((file) => {
                  console.log('convertURLToFile ~ file', file)
                  const fileUrl = URL.createObjectURL(file)
                  console.log('convertURLToFile fileUrl', fileUrl)
                  setAudioFile({
                    url: fileUrl,
                    name: file.name,
                    loading: false,
                  })
                })
                .catch((ex) => {
                  console.log('convertURLToFile ~ ex', ex)
                  setAudioFile({
                    name: '音频转化异常',
                    loading: false,
                  })
                })
            }}
          >
            在线文件URL 转 File
          </button>
        </div>
      </div>
      <div className="card">
        <div className="main">
          <div className="item">
            <div className="main-label">转化视频展示</div>
            <div className="main-content">
              <video
                src={videoFile?.url}
                controls
                preload="metadata"
                autoPlay={false}
              >
                {/* <source src={videoFile?.url} type='video/*' /> */}
                您的浏览器不支持video标签。
              </video>
            </div>
          </div>
          <div className="item">
            <div className="main-label">文件名称</div>
            <div className="main-content">
              {videoFile?.loading ? (
                <div className="loading-text">视频下载转化中...</div>
              ) : (
                <div>{videoFile?.name}</div>
              )}
            </div>
          </div>
          <div className="item">
            <div className="main-label">源文件地址</div>
            <div className="main-content">
              <div>{demoVideoFile.url}</div>
            </div>
          </div>
          <div className="item">
            <div className="main-label">转化文件地址</div>
            <div className="main-content">
              <div>{videoFile?.url}</div>
            </div>
          </div>
        </div>
        <div className="toolbar">
          <button
            onClick={() => {
              setVideoFile({
                loading: true,
              })
              convertURLToBlob(demoVideoFile.url)
                .then((blob) => {
                  console.log('convertURLToBlob ~ blob', blob)
                  const fileUrl = URL.createObjectURL(blob)
                  console.log('convertURLToBlob fileUrl', fileUrl)
                  setVideoFile({
                    url: fileUrl,
                    name: 'Blob视频',
                    loading: false,
                  })
                })
                .catch((ex) => {
                  console.log('convertURLToBlob ~ ex', ex)
                  setVideoFile({
                    name: '视频转化异常',
                    loading: false,
                  })
                })
            }}
          >
            在线文件URL 转 Blob
          </button>
          <button
            onClick={() => {
              setVideoFile({
                loading: true,
              })
              convertURLToFile(demoVideoFile.url, {
                fileName: '演示视频文件',
                fileType: demoVideoFile.type,
              })
                .then((file) => {
                  console.log('convertURLToFile ~ file', file)
                  const fileUrl = URL.createObjectURL(file)
                  console.log('convertURLToFile fileUrl', fileUrl)
                  setVideoFile({
                    url: fileUrl,
                    name: file.name,
                    loading: false,
                  })
                })
                .catch((ex) => {
                  console.log('convertURLToFile ~ ex', ex)
                  setVideoFile({
                    name: '视频转化异常',
                    loading: false,
                  })
                })
            }}
          >
            在线文件URL 转 File
          </button>
        </div>
      </div>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))
```

### 其他文件操作方法

```tsx
import {
  getFileExtByPath,
  getFileNameByPath,
  getFileFullNameByPath,
} from '@rc-utils/h5-file'
import React, { useState } from 'react'
import ReactDOM from 'react-dom'

const demoFileFullPath =
  'htttp://www.xxxx.com/files/demo-image.png?param1=par1&param2=par2'

const App = () => {
  const [fileFullPath, setFileFullPath] = useState<string>(demoFileFullPath)
  const [fileObj, setFileObj] = useState<{
    ext: string
    name: string
    fullName: string
  }>()

  useEffect(() => {
    setFileObj({
      ext: getFileExtByPath(fileFullPath),
      name: getFileNameByPath(fileFullPath),
      fullName: getFileFullNameByPath(fileFullPath),
    })
  }, [fileFullPath])

  return (
    <div className="card">
      <div className="main">
        <div className="item">
          <div className="main-label">自定义文件路径</div>
          <div className="main-content">
            <div className="content-input">
              <input
                type="url"
                defaultValue={demoFileFullPath}
                id="filePath"
                placeholder="请输入文件全路径"
              />
            </div>
            <div className="content-toolbar">
              <button
                onClick={() => {
                  const element = document.getElementById(
                    'filePath'
                  ) as HTMLInputElement
                  const filePath = element.value
                  setFileFullPath(filePath)
                }}
              >
                获取
              </button>
            </div>
          </div>
        </div>
        <div className="item">
          <div className="main-label">文件全路径</div>
          <div className="main-content">
            <div>{fileFullPath}</div>
          </div>
        </div>
        <div className="item">
          <div className="main-label">文件后缀</div>
          <div className="main-content">
            <div>{fileObj?.ext}</div>
          </div>
        </div>
        <div className="item">
          <div className="main-label">文件名称</div>
          <div className="main-content">
            <div>{fileObj?.name}</div>
          </div>
        </div>
        <div className="item">
          <div className="main-label">文件全名</div>
          <div className="main-content">
            <div>{fileObj?.fullName}</div>
          </div>
        </div>
      </div>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))
```