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 = null
constructor() {
makeObservable(this)
}
@action setFilename(newFilename: string) {
this.filename = newFilename
}
@action setFile(newFile: any) {
this.file = newFile
}
@action upload() {
this.isUploading = true
return new Promise((resolve, reject) => {
Uploader.add(this.file, this.filename)
.then((serverFile: any) => {
this.serverFile = serverFile
resolve(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 other
band 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
},