tl;dr: CS50 IDE won't let me upload certain kinds of files (via a form on a webpage) without any explanation.

I'm writing the function upload_file() that allows the user to upload a file. (It's a CSV file [generated by Google Dictionary] that will later be parsed and added to the database.) My goal is to upload the file to /static/uploads folder in my working directory.

So, upload_file() works but CS50 won't let me upload certain files (while other files are uploaded OK). It's displaying a 500 Internal Server Error without any information. It raises an error before accessing my app route with POST when I click "Upload," so I don't get any information at all—nothing happens.

INFO:werkzeug: - - [06/Aug/2020 09:25:26] "GET / HTTP/1.0" 200 -
INFO:werkzeug: - - [06/Aug/2020 09:25:26] "GET /static/styles.css HTTP/1.0" 200 -
INFO:werkzeug: - - [06/Aug/2020 09:25:28] "GET /upload_file HTTP/1.0" 200 -
INFO:werkzeug: - - [06/Aug/2020 09:25:28] "GET /static/styles.css HTTP/1.0" 200 -

Here's what successful output looks like:

INFO:werkzeug: - - [06/Aug/2020 09:29:16] "POST /upload_file HTTP/1.0" 302 -

So, it doesn't work on:

  • Google Dictionary CSVs (generally) (size: 64 KB)
  • Images

It does work on:

  • CSV files generated by my web app (size: 3 KB)
  • Truncated Google Dictionary CSVs (about 4 lines)

In case anyone would like to try it out, here's a Google Drive folder containing these sample files: LINK. (In the filename, "Y" means that the file uploads successfully, "N" means it doesn't.)

Here's my source code (most of it comes from Flask documentation) [irrelevant imports and other functions are excluded].

import os
from flask import Flask, flash, request, redirect, url_for, send_from_directory, render_template
from werkzeug.utils import secure_filename

from helpers import allowed_file

UPLOAD_FOLDER = '/home/ubuntu/project/static/uploads'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'csv'}

@app.route('/upload_file', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        # Check if post request has file part
        if 'file' not in request.files:
            print("'file' not in request.files")
            flash('No file part')
            return redirect(request.url)
        # Store file as variable
        file = request.files['file']

        # Check filename
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename, ALLOWED_EXTENSIONS):
            filename = secure_filename(file.filename)

            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            flash('File saved')
            return redirect("/upload_file")

        return render_template("upload.html")

The allowed_file() function:

def allowed_file(filename, ALLOWED_EXTENSIONS):
    '''Check if an extension is valid'''
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

My HTML form:

<form action="/upload_file" method="post" enctype="multipart/form-data">
    <input class="form-control-file" type="file" name="file">
    <button class="btn btn-primary m-1" type="submit">Upload</button>

So, what might be causing this? And how do I get around it? Are there limitations on uploads in CS50 IDE? I've tried uploading this file running on localhost:5000 (I've used Atom and a simple Flask tutorial) and it worked fine.

Thank you!

You must log in to answer this question.

Browse other questions tagged .