File & Blob
基本概念
const blob = new Blob(['data'], 'type');
const file = new File(['data'], 'fileName', 'type')
console.log( await blob.arrayBuffer() );
console.log( await file.arrayBuffer() );
const fileReader = new FileReader();
fileReader.onload = (e) => {
console.log(fileReader.result)
console.log(e.target.result);
}
fileReader.readAsArrayBuffer(file);
const dataView = new DataView( await blob.arrayBuffer())
console.log(dataView);
console.log(dataView.getUint8(1));
dataView.setUint8(1, 65)
-
file
的原型其实是Blob
, 只不过多了文件名 , 数据层面是相同的 -
arrayBuffer()
返回Promise
, 需要通过await
调用 -
对于
FileReader
构造函数来说 ,e.target
就是fileReader
, 所以e.target.result
就是fileReader.result
, 都还是ArrayBuffer
-
对于
DataView
构造函数来说 ,getUint8(number)
, 表示获取第number
个字节的内容setUint8(number , value)
, 表示设置第number
个字节的内容为value
打开文件
const openFile = () => {
const onFileChange = async (e) => {
console.log(e.target.files)
console.log(e.target.files[0])
console.log(await e.target.files[0].arrayBuffer())
}
return (
<input type="file" onChange={onFileChange} />
)
}
const dragFile = () => {
const dragOver = (e) => {
e.preventDefault()
}
const drop = async (e) => {
e.preventDefault()
console.log('files', e.dataTransfer.files);
console.log(e.dataTransfer.files[0]);
console.log(await e.dataTransfer.files[0].arrayBuffer())
}
return (
<div
onDragOver={dragOver}
onDrop={drop}
>
</div>
)
}
const pickFile = () => {
const filePicker = async (e) => {
const pickerOpts = {
types: [
{
description: 'Images',
accept: {
'image/jpeg': ['.jpg', '.jpeg', '.png'],
}
},
],
excludeAcceptAllOption: true,
multiple: false
};
const [fileHandle] = await (window.showOpenFilePicker(pickerOpts));
console.log(fileHandle);
const f = await fileHandle.getFile();
console.log(f);
console.log(await f.arrayBuffer());
}
return (
<button onClick={filePicker}>File Picker</button>
)
}
const fetchFile = () =>{
fetch('./filePath.extension')
.then(response => response.blob())
.then( async (result) => {
console.log(result);
// console.log(await result.text());
console.log(await result.arrayBuffer());
})
.cache((error) => {
console.error(error);
})
}
文件操作
const fileOperation = () => {
const [flieHandle, setFileHandle] = useState();
const save = async (handle) => {
if(!handle) return;
const stream = await handle.createWritable();
await stream.write(ref.current.value);
await stream.close();
}
const onCreate = async () => {
const createFile = await window.showSaveFilePicker();
setFileHandle(createFile);
return createFile
}
const onOpen = async () => {
const [openFile] = await window.showOpenFilePicker();
setFileHandle(openFile);
const f = await openFile.getFile();
ref.current.value = await f.text();
}
const onSave = async (e) => {
e.preventDefault();
if(!fileHandle){
await onCreate();
}
save(flieHandle);
}
const onSaveAs = async (e) => {
e.preventDefault();
const createFile = await onCreate();
save(createFile);
}
return (
<>
<textarea ref={ref}></textarea>
<div>
<button onClick={onCreate}>create</button>
<button onClick={onOpen}>open</button>
<button onClick={onSave}>save</button>
<button onClick={onSaveAs}>save as</button>
</div>
</>
)
}
image&canvas
const imageCanvas = () => {
const refCanvas = useRef();
const [objUrl, setObjUrl] = useState();
const [context, setContext] = useState();
useEffect(()=>{
const ctx = refCanvas.current.getContext('2d');
if(!ctx) setContext(ctx)
})
const color2Gray = (imgData) => {
for (let index = 0; i = 0; i < imgData.data.width; i++) {
for (let j = 0; j < imgData.data.height; j++; index+=4) {
const red = imgData.data[index];
const green = imgData.data[index + 1];
const blue = imgData.data[index + 2];
const ave = (red + green + blue) / 3;
imgData.data[index] = ave;
imgData.data[index + 1] = ave;
imgData.data[index + 2] = ave;
}
}
}
const onOpen = async () => {
const [fileHandle] = await window.showOpenFilePicker();
const f = await fileHandle.getFile();
const url = URL.createObjectURL(f);
setObjUrl(url);
const image = new Image();
image.width = 100;
image.onload = () => {
context.drawImage(image, 0, 0, 100, 100);
const data = context.getImageData(0, 0, 100, 100);
color2Gray(data);
context.putImageData(data, 0, 0, 0, 0, data.width, data.height);
}
image.src = url;
}
const onSave = async (handle) => {
if(!handle) return;
const stream = await handle.createWritable();
refCanvas.current.toBlob(async (b) => {
if(!b) return;
await stream.write(b);
await stream.close();
})
}
return (
<>
<img src={objUrl} width={300} alt='img' />
<canvas ref={refCanvas} width={100} height={100}>
This browser does not support canvas
</canvas>
<div>
<button onClick={onOpen}>open</button>
<button onClick={onSave}>save</button>
</div>
</>
)
}
BlobURL&DataURL
URL.createObjectURL(blob)
: blob url , 可以在新标签页中打开FileReader.readAsDataURL(file)
: data url , 程序用不允许在新标签页中打开 , 但是可以通过手动复制的方式打开<a>
: 可以设置属性download
来下载内容
const URL = () => {
type TYPE = 'text' | 'image' | '';
const [type, setType] = useState<TYPE>();
const [objUrl, setObjUrl] = useState();
const onFetch = (type: TYPE, filepath: string) => {
fetch(filepath)
.then(response => response.blob())
.then( async (result: Blob) => {
setObjUrl(URL.createObjectURL(result));
setType(type);
// const reader = new FileReader();
// reader.onload = (e) => {
// setObjUrl(e.target.result);
// setType(type);
// }
// reader.readAsDataURL(result);
})
.cache(error => {
console.error(error);
})
}
return (
<>
<button onClick={onFetch('text', './filepath.text')}>text</button>
<button onClick={onFetch('image', './filepath.image')}>image</button>
{
type === 'text'
? <iframe src={objUrl} width={300}></iframe>
: <img src={objUrl} width={300} alt='img' />
}
</>
)
}
访问文件夹
window.showDirectoryPicker
dirHandle.values
dirHandle.getFileHandle
const folder = () =>{
const ref = useRef();
const [list, setList] = useState([]);
const [dirHandle, setDirHandle] = useState();
const onOpenDir = async () => {
const fsfHandle = await window.showDirectoryPicker();
if(!fsfHandle) return;
console.log(fsfHandle);
const entries = await fsfHandle.values();
console.log(entries);
const items = []
for await ( const entry of entries) {
console.log(entry, entry.name);
if(entry.isFile){
items.push(`${entry.name}${entry.kind === 'file' ? '' : `${entry.kind}`}`);
}
}
if(items.length) {
setDirHandle(fsfHandle);
setList(items);
}
}
const onClickFileName = async (filename) => {
const fHandle = await dirHandle.getFileHandle(filename);
console.log(fHandle);
if(fHandle.kind === 'file'){
const f = await fHandle.getFile();
if(!f) return;
console.log(f);
const t = await f.text();
ref.current.value = t;
}
}
return (
<>
<button onClick={onOpenDir}>folder</button>
<textarea ref={ref}></textarea>
</>
)
}
文件上传
formData()
格式