@rc-utils/h5-file
安装
使用 npm:
$ npm i -g npm
$ npm i @rc-utils/h5-file
使用方法
直接引用
import * as h5FileUtils from '@rc-utils/h5-file'
File
| Blob
| Base64
之间互相转化
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'))
File
| Blob
对象
文件 URL 下载转存为 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'))
其他文件操作方法
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¶m2=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'))