model 中创建图片上传 API
const Uploader = {add(file: any, filename: string) {const item = new AV.Object('Image')const avFile = new AV.File(filename, file)item.set('filename', filename)item.set('owner', AV.User.current())item.set('url', avFile)return new Promise((resolve, reject) => {item.save().then((serverFile) => {console.log('保存成功')resolve(serverFile)},(error) => {console.log('保存失败')reject(error)})})},}
store 中创建 ImageStore, 用于管理图片数据
import { makeObservable, observable, action } from 'mobx'import { Uploader } from '../models'class ImageStore {@observable filename = ''@observable file: any = null@observable isUploading = false@observable serverFile: any = nullconstructor() {makeObservable(this)}@action setFilename(newFilename: string) {this.filename = newFilename}@action setFile(newFile: any) {this.file = newFile}@action upload() {this.isUploading = truereturn new Promise((resolve, reject) => {Uploader.add(this.file, this.filename).then((serverFile: any) => {this.serverFile = serverFileresolve(serverFile)}).catch((err: any) => {console.log('上传失败')reject(err)}).finally(() => {this.isUploading = false})})}}export default new ImageStore()
原生 input 实现简易上传
import { MutableRefObject, useRef } from 'react'import { useStore } from '../store'const Uploader = () => {const inputRef = useRef() as MutableRefObject<HTMLInputElement>const { ImageStore } = useStore()const handleUpload = () => {if (inputRef.current.files && inputRef.current.files.length > 0) {ImageStore.setFile(inputRef.current.files[0])ImageStore.setFilename(inputRef.current.files[0].name)ImageStore.upload().then((file) => console.dir(file)).catch((err) => {console.error(err)})}}return (<><h2>文件上传</h2><input type="file" ref={inputRef} onChange={handleUpload} /></>)}export default Uploading
改用 antd 实现图片上传
使用 Upload 组件, 上传逻辑写在 beforeUpload 属性中
import { MutableRefObject, useRef } from 'react'import { useStore } from '../store'import { Upload } from 'antd';import { InboxOutlined } from '@ant-design/icons';const { Dragger } = Upload;const Uploader = () => {const { ImageStore } = useStore()const props = {showUploadList: false,beforeUpload: (file:any) => {ImageStore.setFile(file)ImageStore.setFilename(file.name)ImageStore.upload().then((file) => console.dir(file)).catch((err) => {console.error(err)})return false;},}return (<><h2>文件上传</h2><Dragger {...props}><p className="ant-upload-drag-icon"><InboxOutlined /></p><p className="ant-upload-text">Click or drag file to this area to upload</p><p className="ant-upload-hint">Support for a single or bulk upload. Strictly prohibit from uploading company data or otherband files</p></Dragger><div><h2>保存地址</h2>{ImageStore.serverFile ? ImageStore.serverFile.attributes.url.attributes.url : ''}</div></>)}export default Uploader
上传结果展示
<div>{ImageStore.serverFile? (<Result><h2>上传结果</h2><dl><dt>线上地址</dt><dd><a target="_blank" href={ImageStore.serverFile.attributes.url.attributes.url} rel="noreferrer">{ImageStore.serverFile.attributes.url.attributes.url}</a></dd><dt>文件名</dt><dd><input className="filename" type="text" value={ImageStore.filename} readOnly /></dd><dt>图片预览</dt><dd><img src={ImageStore.serverFile.attributes.url.attributes.url} alt="" /></dd><dt>更多尺寸</dt><dd>...</dd></dl></Result>): ''}</div>
const Result = styled.div`margin-top: 20px;> dl {border: 1px dashed #6ebcfc;background: #fafafa;padding: 20px;.filename {border: 1px solid #999;width: 100%;padding: 4px;&:focus {outline: none;}}> dt {padding-bottom: 6px;}a {display: inline-block;width: 100%;border: 1px solid #999;padding: 4px;white-space: wrap;word-wrap:break-word;background: white;}img {max-height: 280px;max-width: 100%;object-fit: contain;}}`
限制图片的格式和大小
在 Dragger 组件的 beforeUpload 属性中添加限制
beforeUpload: (file: any) => {ImageStore.setFile(file)ImageStore.setFilename(file.name)if (!/(svg$)|(png$)|(jpg$)|(jpeg$)|(gif$)/gi.test(file.type)) {message.error('仅支持 png/svg/jpg/jpeg/gif 格式的图片')return false}if (file.size > 2048 * 1024) {message.error('图片最大支持2M')return false}ImageStore.upload().then((file) => console.dir(file)).catch((err) => {console.error(err)})return false},
