binary-file-text.js 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import React, { useState, useEffect } from 'react'
  2. import PropTypes from 'prop-types'
  3. const MAX_FILE_SIZE = 2 * 1024 * 1024
  4. export default function BinaryFileText({ file, onLoad, onError }) {
  5. const [textPreview, setTextPreview] = useState('')
  6. const [shouldShowDots, setShouldShowDots] = useState(false)
  7. useEffect(() => {
  8. let path = `/project/${window.project_id}/file/${file.id}`
  9. fetch(path, { method: 'HEAD' })
  10. .then(response => {
  11. if (!response.ok) throw new Error('HTTP Error Code: ' + response.status)
  12. return response.headers.get('Content-Length')
  13. })
  14. .then(fileSize => {
  15. let truncated = false
  16. let maxSize = null
  17. if (fileSize > MAX_FILE_SIZE) {
  18. truncated = true
  19. maxSize = MAX_FILE_SIZE
  20. }
  21. if (maxSize != null) {
  22. path += `?range=0-${maxSize}`
  23. }
  24. fetch(path)
  25. .then(response => {
  26. response.text().then(text => {
  27. if (truncated) {
  28. text = text.replace(/\n.*$/, '')
  29. }
  30. setTextPreview(text)
  31. onLoad()
  32. setShouldShowDots(truncated)
  33. })
  34. })
  35. .catch(err => {
  36. onError()
  37. console.error(err)
  38. })
  39. })
  40. .catch(err => {
  41. onError()
  42. })
  43. }, [file.id, onError, onLoad])
  44. return (
  45. <div>
  46. {textPreview && (
  47. <div className="text-preview">
  48. <div className="scroll-container">
  49. <p>{textPreview}</p>
  50. {shouldShowDots && <p>...</p>}
  51. </div>
  52. </div>
  53. )}
  54. </div>
  55. )
  56. }
  57. BinaryFileText.propTypes = {
  58. file: PropTypes.shape({ id: PropTypes.string }).isRequired,
  59. onLoad: PropTypes.func.isRequired,
  60. onError: PropTypes.func.isRequired
  61. }