github.com/minio/console@v1.4.1/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 versionID: actualInfo.version_id || "", 55 }) 56 .then((res) => { 57 let metadata = get(res.data, "objectMetadata", {}); 58 setIsMetaDataLoaded(true); 59 setMetaData(metadata); 60 }) 61 .catch((err) => { 62 console.error( 63 "Error Getting Metadata Status: ", 64 err, 65 err?.detailedError, 66 ); 67 setIsMetaDataLoaded(true); 68 }); 69 } 70 }, [bucketName, objectName, isMetaDataLoaded, actualInfo.version_id]); 71 72 useEffect(() => { 73 if (bucketName && objectName) { 74 fetchMetadata(); 75 } 76 }, [bucketName, objectName, fetchMetadata]); 77 78 let path = ""; 79 80 if (actualInfo) { 81 const encodedPath = encodeURLString(actualInfo.name || ""); 82 let basename = document.baseURI.replace(window.location.origin, ""); 83 path = `${window.location.origin}${basename}api/v1/buckets/${bucketName}/objects/download?preview=true&prefix=${encodedPath}`; 84 if (actualInfo.version_id) { 85 path = path.concat(`&version_id=${actualInfo.version_id}`); 86 } 87 } 88 89 let objectType: AllowedPreviews = previewObjectType(metaData, objectName); 90 91 const iframeLoaded = () => { 92 setLoading(false); 93 }; 94 95 return ( 96 <Fragment> 97 {objectType !== "none" && loading && ( 98 <Grid item xs={12}> 99 <ProgressBar /> 100 </Grid> 101 )} 102 {isMetaDataLoaded ? ( 103 <Box 104 sx={{ 105 textAlign: "center", 106 "& .iframeContainer": { 107 border: "0px", 108 flex: "1 1 auto", 109 width: "100%", 110 height: 250, 111 backgroundColor: "transparent", 112 borderRadius: 5, 113 114 "&.image": { 115 height: 500, 116 }, 117 "&.audio": { 118 height: 150, 119 }, 120 "&.video": { 121 height: 350, 122 }, 123 "&.fullHeight": { 124 height: "calc(100vh - 185px)", 125 }, 126 }, 127 "& .iframeBase": { 128 backgroundColor: "#fff", 129 }, 130 "& .iframeHidden": { 131 display: "none", 132 }, 133 }} 134 > 135 {objectType === "video" && ( 136 <video 137 style={{ 138 width: "auto", 139 height: "auto", 140 maxWidth: "calc(100vw - 100px)", 141 maxHeight: "calc(100vh - 200px)", 142 }} 143 autoPlay={true} 144 controls={true} 145 muted={false} 146 playsInline={true} 147 onPlay={iframeLoaded} 148 > 149 <source src={path} type="video/mp4" /> 150 </video> 151 )} 152 {objectType === "audio" && ( 153 <audio 154 style={{ 155 width: "100%", 156 height: "auto", 157 }} 158 autoPlay={true} 159 controls={true} 160 muted={false} 161 playsInline={true} 162 onPlay={iframeLoaded} 163 > 164 <source src={path} type="audio/mpeg" /> 165 </audio> 166 )} 167 {objectType === "image" && ( 168 <img 169 style={{ 170 width: "auto", 171 height: "auto", 172 maxWidth: "100vw", 173 maxHeight: "100vh", 174 }} 175 src={path} 176 alt={"preview"} 177 onLoad={iframeLoaded} 178 /> 179 )} 180 {objectType === "pdf" && ( 181 <Fragment> 182 <PreviewPDF 183 path={path} 184 onLoad={iframeLoaded} 185 loading={loading} 186 downloadFile={() => 187 downloadObject(dispatch, bucketName, path, actualInfo) 188 } 189 /> 190 </Fragment> 191 )} 192 {objectType === "none" && ( 193 <div> 194 <InformativeMessage 195 message=" File couldn't be previewed using file extension or mime type. Please 196 try Download instead" 197 title="Preview unavailable" 198 sx={{ margin: "15px 0" }} 199 /> 200 </div> 201 )} 202 {objectType !== "none" && 203 objectType !== "video" && 204 objectType !== "audio" && 205 objectType !== "image" && 206 objectType !== "pdf" && ( 207 <div className={`iframeBase ${loading ? "iframeHidden" : ""}`}> 208 <iframe 209 src={path} 210 title="File Preview" 211 allowTransparency 212 className={`iframeContainer ${ 213 isFullscreen ? "fullHeight" : objectType 214 }`} 215 onLoad={iframeLoaded} 216 > 217 File couldn't be loaded. Please try Download instead 218 </iframe> 219 </div> 220 )} 221 </Box> 222 ) : null} 223 </Fragment> 224 ); 225 }; 226 export default PreviewFile;