我试图在浏览器中预览多个图像,然后再使用ReactJS和FileReader()
API将它们上传到服务器。我的问题是,每次我选择一些图像进行预览时,仅显示最后一张图像。
我的代码如下:
class App extends Component {
constructor(props){
super(props);
this.state = {
id: "upload-photo",
imageURI: null
}
}
buildImgTag(){
let imgTag = null;
if (this.state.imageURI !== null) {
imgTag = (
<div className="photo-container">
<img className="photo-uploaded" src={this.state.imageURI} alt="Photo uploaded"/>
</div>
);
return imgTag;
}
}
readURI(e){
if (e.target.files) {
let filesAmount = e.target.files.length;
let i;
for (i = 0; i < filesAmount; i++) {
let reader = new FileReader();
reader.onload = function(ev) {
this.setState (
{
imageURI: ev.target.result
}
)
}.bind(this);
reader.readAsDataURL(e.target.files[i]);
}
}
}
handleChange(e){
this.readURI(e);
if (this.props.onChange !== undefined) {
this.props.onChange(e);
}
}
render() {
const imgTag = this.buildImgTag();
return (
<div className="container">
<div className="row justify-content-center">
<div className="col-md-6">
<div className="card">
<div className="card-header" style={{backgroundColor: 'rgb(232, 245, 253)', borderTopLeftRadius: '4px', borderTopRightRadius: '4px', display: 'flex', maxHeight: '50vh', minHeight: '25vh', overflow: 'hidden'}}>
<div className="avatar">
<img src="http://laratweet.local:8080/images/avatar-default.png" alt="User Avatar" className="user-avatar"/>
</div>
<div id="textEditor">
<form method="post" action="" encType="multipart/form-data">
<textarea name="" id="richTextArea" placeholder="What's happening?"></textarea>
{imgTag}
<div id="theRibbon">
<div>
<input
id={this.state.id}
type="file"
name=""
accept="image/gif,image/jpeg,image/jpg,image/png,video/mp4,video/x-m4v"
title="Add photos or video"
onChange={this.handleChange.bind(this)}
multiple
/>
<label htmlFor={this.state.id}>
<figure>
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="27"
viewBox="0 0 20 17" className="upload-icon">
<path
d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"/>
</svg>
</figure>
<span className="tooltiptext">Add photos or video</span>
</label>
</div>
<button type="submit" className="tweet">Tweet</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
我希望所有选择的图像都可以在浏览器中显示/预览,但是只有最后一张图像可以预览。我在做什么错了?
答案 0 :(得分:1)
这里的主要问题是您的App
组件状态目前只能跟踪一个imageURI
。考虑修改state
模型,以便可以存储和呈现imageURI
数组:
this.state = {
id: "upload-photo",
imageArray: [] /* Replace imageURI with an array for multiple images */
}
接下来,您需要更新readURI()
,以便它以组件状态存储多个图像。一种方法是使用Promise.all()
异步加载图像数组:
readURI(e){
if (e.target.files) {
/* Get files in array form */
const files = Array.from(e.target.files);
/* Map each file to a promise that resolves to an array of image URI's */
Promise.all(files.map(file => {
return (new Promise((resolve,reject) => {
const reader = new FileReader();
reader.addEventListener('load', (ev) => {
resolve(ev.target.result);
});
reader.addEventListener('error', reject);
reader.readAsDataURL(file);
}));
}))
.then(images => {
/* Once all promises are resolved, update state with image URI array */
this.setState({ imageArray : images })
}, error => {
console.error(error);
});
}
}
最后,您只需要更新buildImgTag()
即可呈现多个图像。一种解决方法可能是:
buildImgTag(){
return <div className="photo-container">
{
this.state.imageArray.map(imageURI =>
(<img className="photo-uploaded" src={imageURI} alt="Photo uploaded"/>))
}
</div>
}
此外,here is a jsFiddle显示了实际的文件读取逻辑。 希望有帮助
答案 1 :(得分:1)
Tentei durante um dia to do a resposta do amigo @ Dacre Denny e acabei utilizando aprima linha de suaresolução,bass as respostassãonativas do JavaScript FileReader() 中的示例,请使用示例性的图像作为 base64 数据集,nãotenho certeza ... >
Base64 de uma forma muito的Acabei resolvendo sem转换器“ mais simples ” 总理声明国家
const [files, setFiles] = useState([]);
const [previews, setPreviews] = useState([]);
const [files, setFiles] = useState([]);
...
const handleUpload = (event) => {
const fileList = Array.from(event.target.files);
setFiles(fileList); //Passei o valor de fileList para o State Files
const mappedFiles = fileList.map((file) => ({
...file,
preview: URL.createObjectURL(file),
}));
setPreviews(mappedFiles); };
... Em meu Styled-Component de上传:
<UploadPhoto type="file" id="files" accept="image/*" multiple="true" onChange={(e) => handleUpload(e)} />
最终结局array.Map
if (previews.length > 0) {
return (
<FormGroup> //styled-component (div) para organizar os itens do form
<UploadContainer> //styled-component (div) display: flex para suportar as imagens
{previews.map((file) => <ImgUpload preview={file.preview} />)} //styled-component
//(div) que se repete de acordo com o número de imagens
</UploadContainer>
</FormGroup>
);
}
以渐进图像的形式显示背景图像,作为背景图像,作为重复图像背景重复:不重复,背景尺寸:封面e背景位置:50%50 %
export const ImgUpload = styled.div`
flex-direction: row;
text-align: center;
margin: 10px;
background-image: ${(props) => (props.preview ? `url(${props.preview})` : null)} ;
min-height: 100px;
min-width: 100px;
border-radius: 5px;
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
margin-right: 5px;
`;
答案 2 :(得分:0)
对于那些正在寻找相同答案的人,有一个更清洁的选项,它不涉及使用javascript以外的其他东西:
HTML:
<!DOCTYPE html>
<html>
<head>
<title>File API - FileReader as Data URL</title>
</head>
<body>
<header>
<h1>File API - FileReader</h1>
</header>
<article>
<label for="files">Select multiple files: </label>
<input id="files" type="file" multiple/>
<output id="result" />
</article>
</body>
</html>
CSS:
body
{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1
{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail
{
height: 100px;
margin: 10px;
}
JAVASCRIPT
window.onload = function()
{
//Check File API support
if ( window.File && window.FileList && window.FileReader )
{
var filesInput = document.getElementById("files");
filesInput.addEventListener
(
"change", function ( event )
{
var files = event.target.files; //FileList object
var output = document.getElementById ( "result" );
for ( var i = 0; i< files.length; i++ )
{
var file = files [ i ];
//Only pics
if ( !file.type.match ( 'image' ) )
continue;
var picReader = new FileReader();
picReader.addEventListener
(
"load", function ( event )
{
var picFile = event.target;
var div = document.createElement ( "div" );
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" + "title='" + picFile.name + "'/>";
output.insertBefore ( div, null );
}
);
//Read the image
picReader.readAsDataURL ( file );
}
}
);
}
else
{
console.log ( "Your browser does not support File API" );
}
}