0
0
Remixframework~20 mins

File uploads and streaming in Remix - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
File Uploads & Streaming Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
component_behavior
intermediate
2:00remaining
What happens when a file upload form is submitted in Remix?

Consider a Remix route with a form that uploads a file using enctype='multipart/form-data'. What does Remix do with the uploaded file data in the action function?

Remix
export const action = async ({ request }) => {
  const formData = await request.formData();
  const file = formData.get('file');
  // What is the type of 'file' here?
  return null;
};
AThe 'file' is a File object representing the uploaded file, accessible for streaming or reading.
BThe 'file' is a string containing the file's path on the server's disk.
CThe 'file' is undefined because Remix does not support file uploads in action functions.
DThe 'file' is a Buffer containing the entire file content loaded in memory.
Attempts:
2 left
💡 Hint

Think about how formData.get() works with file inputs in web APIs.

📝 Syntax
intermediate
2:00remaining
Which code correctly streams an uploaded file to disk in Remix?

You want to save an uploaded file to disk inside an action function in Remix. Which code snippet correctly streams the file to a local path?

Remix
export const action = async ({ request }) => {
  const formData = await request.formData();
  const file = formData.get('file');
  // Save file to disk here
};
A
const dest = fs.createWriteStream('./uploads/' + file.name);
await file.stream().pipe(dest);
B
const dest = fs.createWriteStream('./uploads/' + file.name);
file.stream().pipe(dest); await dest.finished();
C
const dest = fs.createWriteStream('./uploads/' + file.name);
await new Promise(resolve => file.stream().pipe(dest).on('finish', resolve));
D
const dest = fs.createWriteStream('./uploads/' + file.name);
file.stream().pipe(dest);
Attempts:
2 left
💡 Hint

Remember that pipe returns the destination stream, and you need to wait for the stream to finish writing.

🔧 Debug
advanced
2:30remaining
Why does this Remix file upload code cause a memory leak?

Review the following action function code snippet. Why might it cause a memory leak when uploading large files?

Remix
export const action = async ({ request }) => {
  const formData = await request.formData();
  const file = formData.get('file');
  const buffer = await file.arrayBuffer();
  await fs.promises.writeFile('./uploads/' + file.name, Buffer.from(buffer));
  return null;
};
ABecause the file name is not sanitized, causing a path traversal vulnerability.
BBecause <code>writeFile</code> does not support Buffer inputs, causing a silent failure.
CBecause <code>formData.get()</code> returns undefined for files, so <code>buffer</code> is null.
DBecause it reads the entire file into memory with <code>arrayBuffer()</code>, which can exhaust memory for large files.
Attempts:
2 left
💡 Hint

Consider how large files are handled in memory when using arrayBuffer().

🧠 Conceptual
advanced
2:30remaining
How does Remix handle streaming file uploads differently from traditional Express apps?

Which statement best describes how Remix's file upload handling differs from a typical Express.js app using multer middleware?

ARemix uses the native <code>Request</code> web API and <code>formData()</code> to access file streams directly without middleware, while Express relies on middleware to parse multipart data.
BRemix requires explicit middleware like <code>multer</code> to parse file uploads, similar to Express.
CRemix automatically saves uploaded files to a temporary folder before the <code>action</code> runs, unlike Express which streams directly.
DRemix does not support streaming uploads and buffers all files in memory, unlike Express.
Attempts:
2 left
💡 Hint

Think about the web platform APIs Remix builds on compared to Node.js middleware.

state_output
expert
3:00remaining
What is the output of this Remix loader streaming response code?

Given the following Remix loader function that streams a text response, what will the client receive?

Remix
export const loader = () => {
  const stream = new ReadableStream({
    start(controller) {
      controller.enqueue(new TextEncoder().encode('Hello '));
      setTimeout(() => {
        controller.enqueue(new TextEncoder().encode('World!'));
        controller.close();
      }, 100);
    }
  });
  return new Response(stream, { headers: { 'Content-Type': 'text/plain' } });
};
AThe client receives an error because <code>setTimeout</code> cannot be used inside a ReadableStream.
BThe client receives 'Hello World!' as a streamed response with a slight delay before 'World!' appears.
CThe client receives 'Hello ' immediately and 'World!' after a 100ms delay, but as two separate responses.
DThe client receives only 'Hello ' because the stream closes before 'World!' is enqueued.
Attempts:
2 left
💡 Hint

Consider how ReadableStream and controller.enqueue work asynchronously.