←back to thread

669 points danso | 1 comments | | HN request time: 0.3s | source
Show context
snazz ◴[] No.23261598[source]
Here's the relevant frontend source code for the file upload picker, if anyone's wondering (webpack://src/components/exam/submissions/FileInput.js):

  <input
            type="file"
            ref={inputRef}
            name="fileupload"
            disabled={disabled}
            accept={EXTENSIONS[type]}
            data-cb-element="no-cb"
            onChange={async e => {
              const [file] = Object.keys(e.target.files).map(key => e.target.files[key])
              const fileSizeInMb = file.size/(CONVERSION_BASE*CONVERSION_BASE)
              const fileSizeInKb = file.size/CONVERSION_BASE
              const split = file.name.split('.')
              const fileType = split[split.length-1].toLowerCase()
              const extensions = EXTENSIONS[type].split(', ')
              const isAllowedExtension = extensions.includes(`.${fileType}`)
              const alreadyExists = files.find(f => f.name === file.name && f.size === file.size && f.lastModified === file.lastModified)
              let error

              if (alreadyExists)
                error = { title: 'You have already uploaded a file with the same name.', details: 'Please attach a different file.' }
              else if (!isAllowedExtension)
                error = { title: 'This file type is not acceptable.', details: 'Please check the requirements, save your file in one of the accepted formats, and resubmit.' }
              else if (fileSizeInKb <= minSize)
                error = { title: 'Your file is too small.', details: 'Please check the file-size requirements, save a larger version, and resubmit.' }
              else if (fileSizeInMb > maxSize)
                error = { title: 'Your file is too big.', details: 'Please check the file-size requirements, save a smaller version, and resubmit. ' }
            
              if (error)
                await setError(<><strong>{error.title}</strong> {error.details}</>)
              else {
                await updateFiles(file)
                setError(null)
              }

              inputRef.current.value = null
            }}
          />
The EXTENSIONS variable is defined here:

  export const EXTENSIONS = {
    [TYPE_DOC]: '.txt, .doc, .docx, .pdf, .odt',
    [TYPE_PHOTO]: '.png, .jpg, .jpeg',
    [TYPE_AUDIO]: '.m4a, .mp3, .wav, .ogg'
  }
replies(4): >>23262022 #>>23262067 #>>23263420 #>>23266424 #
scott_s ◴[] No.23262067[source]
I'm trying to square this with the fact people pointed out downthread, which is that iPhones will automatically convert HEIC images to jpeg from an HTML input form. Perhaps it's the `isAllowedExtension` check? If `e.target.files` is the actual file names on disk (and not whatever temporary file the browser made out of the HEIC file), that would cause a problem.
replies(2): >>23262429 #>>23263533 #
hamandcheese ◴[] No.23263533[source]
I think the issue is that accept is specified only with extensions rather than mime types.
replies(1): >>23264126 #
scott_s ◴[] No.23264126[source]
I wondered that, too, but I couldn't find any HTML documentation that blessed one form as superior to the other. And I would be surprised if Apple automatically converted images for "accept=image/jpg" but not "accept=.jpg".
replies(1): >>23265222 #
1. johnp_ ◴[] No.23265222[source]
Here's the spec:

https://html.spec.whatwg.org/multipage/input.html#attr-input...

> Authors are encouraged to specify both any MIME types and any corresponding extensions when looking for data in a specific format.

> User agents should prevent the user from selecting files that are not accepted by one (or more) of these tokens.