github.com/minio/console@v1.3.0/web-app/src/screens/Console/Buckets/ListBuckets/Objects/Preview/PreviewFileContent.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import React, { Fragment, useCallback, useEffect, useState } from "react"; 18 import { ProgressBar, Grid, Box, InformativeMessage } from "mds"; 19 import get from "lodash/get"; 20 import { AllowedPreviews, previewObjectType } from "../utils"; 21 import { encodeURLString } from "../../../../../../common/utils"; 22 import { api } from "../../../../../../api"; 23 import PreviewPDF from "./PreviewPDF"; 24 import { downloadObject } from "../../../../ObjectBrowser/utils"; 25 import { useAppDispatch } from "../../../../../../store"; 26 import { BucketObject } from "../../../../../../api/consoleApi"; 27 28 interface IPreviewFileProps { 29 bucketName: string; 30 actualInfo: BucketObject; 31 isFullscreen?: boolean; 32 } 33 34 const PreviewFile = ({ 35 bucketName, 36 actualInfo, 37 isFullscreen = false, 38 }: IPreviewFileProps) => { 39 const dispatch = useAppDispatch(); 40 41 const [loading, setLoading] = useState<boolean>(true); 42 43 const [metaData, setMetaData] = useState<any>(null); 44 const [isMetaDataLoaded, setIsMetaDataLoaded] = useState(false); 45 46 const objectName = actualInfo?.name || ""; 47 48 const fetchMetadata = useCallback(() => { 49 if (!isMetaDataLoaded) { 50 const encodedPath = encodeURLString(objectName); 51 api.buckets 52 .getObjectMetadata(bucketName, { 53 prefix: encodedPath, 54 }) 55 .then((res) => { 56 let metadata = get(res.data, "objectMetadata", {}); 57 setIsMetaDataLoaded(true); 58 setMetaData(metadata); 59 }) 60 .catch((err) => { 61 console.error( 62 "Error Getting Metadata Status: ", 63 err, 64 err?.detailedError, 65 ); 66 setIsMetaDataLoaded(true); 67 }); 68 } 69 }, [bucketName, objectName, isMetaDataLoaded]); 70 71 useEffect(() => { 72 if (bucketName && objectName) { 73 fetchMetadata(); 74 } 75 }, [bucketName, objectName, fetchMetadata]); 76 77 let path = ""; 78 79 if (actualInfo) { 80 const encodedPath = encodeURLString(actualInfo.name || ""); 81 let basename = document.baseURI.replace(window.location.origin, ""); 82 path = `${window.location.origin}${basename}api/v1/buckets/${bucketName}/objects/download?preview=true&prefix=${encodedPath}`; 83 if (actualInfo.version_id) { 84 path = path.concat(`&version_id=${actualInfo.version_id}`); 85 } 86 } 87 88 let objectType: AllowedPreviews = previewObjectType(metaData, objectName); 89 90 const iframeLoaded = () => { 91 setLoading(false); 92 }; 93 94 return ( 95 <Fragment> 96 {objectType !== "none" && loading && ( 97 <Grid item xs={12}> 98 <ProgressBar /> 99 </Grid> 100 )} 101 {isMetaDataLoaded ? ( 102 <Box 103 sx={{ 104 textAlign: "center", 105 "& .iframeContainer": { 106 border: "0px", 107 flex: "1 1 auto", 108 width: "100%", 109 height: 250, 110 backgroundColor: "transparent", 111 borderRadius: 5, 112 113 "&.image": { 114 height: 500, 115 }, 116 "&.audio": { 117 height: 150, 118 }, 119 "&.video": { 120 height: 350, 121 }, 122 "&.fullHeight": { 123 height: "calc(100vh - 185px)", 124 }, 125 }, 126 "& .iframeBase": { 127 backgroundColor: "#fff", 128 }, 129 "& .iframeHidden": { 130 display: "none", 131 }, 132 }} 133 > 134 {objectType === "video" && ( 135 <video 136 style={{ 137 width: "auto", 138 height: "auto", 139 maxWidth: "calc(100vw - 100px)", 140 maxHeight: "calc(100vh - 200px)", 141 }} 142 autoPlay={true} 143 controls={true} 144 muted={false} 145 playsInline={true} 146 onPlay={iframeLoaded} 147 > 148 <source src={path} type="video/mp4" /> 149 </video> 150 )} 151 {objectType === "audio" && ( 152 <audio 153 style={{ 154 width: "100%", 155 height: "auto", 156 }} 157 autoPlay={true} 158 controls={true} 159 muted={false} 160 playsInline={true} 161 onPlay={iframeLoaded} 162 > 163 <source src={path} type="audio/mpeg" /> 164 </audio> 165 )} 166 {objectType === "image" && ( 167 <img 168 style={{ 169 width: "auto", 170 height: "auto", 171 maxWidth: "100vw", 172 maxHeight: "100vh", 173 }} 174 src={path} 175 alt={"preview"} 176 onLoad={iframeLoaded} 177 /> 178 )} 179 {objectType === "pdf" && ( 180 <Fragment> 181 <PreviewPDF 182 path={path} 183 onLoad={iframeLoaded} 184 loading={loading} 185 downloadFile={() => 186 downloadObject(dispatch, bucketName, path, actualInfo) 187 } 188 /> 189 </Fragment> 190 )} 191 {objectType === "none" && ( 192 <div> 193 <InformativeMessage 194 message=" File couldn't be previewed using file extension or mime type. Please 195 try Download instead" 196 title="Preview unavailable" 197 sx={{ margin: "15px 0" }} 198 /> 199 </div> 200 )} 201 {objectType !== "none" && 202 objectType !== "video" && 203 objectType !== "audio" && 204 objectType !== "image" && 205 objectType !== "pdf" && ( 206 <div className={`iframeBase ${loading ? "iframeHidden" : ""}`}> 207 <iframe 208 src={path} 209 title="File Preview" 210 allowTransparency 211 className={`iframeContainer ${ 212 isFullscreen ? "fullHeight" : objectType 213 }`} 214 onLoad={iframeLoaded} 215 > 216 File couldn't be loaded. Please try Download instead 217 </iframe> 218 </div> 219 )} 220 </Box> 221 ) : null} 222 </Fragment> 223 ); 224 }; 225 export default PreviewFile;