Flutter web app upload image to backend | Server | Localhost

Created At: 2025-04-23 04:45:04 Updated At: 2025-04-23 04:52:25

Here we will how to upload image to the backend server using flutter web app. Here the code I am going to share always works and I have used in my other projects. Let's get started.

Install file_picker

We have to upload the file_picker plugin. Since we are on web app, we are not going to use image_picker. Of course you may use of the packages, switch between them using kIsWeb among mobile andweb app. Anyway, here we are going to focus on web app of flutter.

Pick files

Now here we will see how pick a image as file. The below code does it, since we are using file_picker, this returns images as PlatformFile object. 

static Future<PlatformFile?> pickImage() async {

  try {

    final result = await FilePicker.platform.pickFiles(

      type: FileType.image,

      withData: true, // important for getting bytes on web

    );

    if (result != null && result.files.isNotEmpty) {

      return result.files.first;

    }

    return null;

  } catch (e, s) {

    logger.e(e, stackTrace: s);

    showSnackBar(message: 'Failed to pick image', type: SnackBarType.error);

    return null;

  }

}

See the above code how it return PlatformFile, just make sure you don't return File object. Once we get the PlatformFile, then we need to send the PlatformFile object to the server and return the url. Then this url we can use as a String type to use NetworkImage.

Server side code

Here first we will see the backend upload code. I am using nodejs as backend, so we will do it using a package called multer. Make sure you install it using as.

npm install multer

Once the package has been installed, make sure you create a file media_helper.js file. This helper file would create disk space and allow image format type. 

const multer = require('multer');

const util = require('util');

const { unlink } = require('fs').promises;

const path = require('path');

const ALLOWED_EXTENSIONS = {

  'image/png': 'png',

  'image/jpeg': 'jpeg',

  'image/jpg': 'jpg',

};

const storage = multer.diskStorage({

  destination: function (_, __, cb) {

    cb(null, 'public/uploads');

  },

  filename: function (_, file, cb) {

    const filename = file.originalname

      .replace(' ', '-')

      .replace('.png', '')

      .replace('.jpg', '')

      .replace('.jpeg', '');

    const extension = ALLOWED_EXTENSIONS[file.mimetype];

    cb(null, `${filename}-${Date.now()}.${extension}`);

  },

});

exports.upload = multer({

  storage: storage,

  limits: { fileSize: 1024 * 1024 * 5 },

  fileFilter: (_, file, cb) => {

    const isValid = ALLOWED_EXTENSIONS[file.mimetype];

    let uploadError = new Error(

      `Invalid image type\n${file.mimetype} is not allowed`

    );

    if (isValid) return cb(null, true);

    return cb(uploadError);

  },

});

exports.deleteImages = async function deleteImages(

  imageUrls,

  continueOnErrorName

) {

  await Promise.all(

    imageUrls.map(async (imageUrl) => {

      const imagePath = path.resolve(

        __dirname,

        '..',

        'public',

        'uploads',

        path.basename(imageUrl)

      );

      try {

        await unlink(imagePath);

      } catch (error) {

        if (error.code === continueOnErrorName) {

          console.error(`Continuing with the next image: ${error.message}`);

        } else {

          console.error(`Error deleting image: ${error.message}`);

          throw error;

        }

      }

    })

  );

};

The above code will create public and uploads folder. If the public folder is not created make sure you create it manually.

Now let's go back to the Flutter code. 

Show image in Flutter

Now if you are successful,it will return status code 200 and url. 

static Future<String?> uploadImageToLocalServer(PlatformFile file) async {

  try {

    if (file.bytes == null || file.name.isEmpty) {

      showSnackBar(message: "Invalid image data", type: SnackBarType.error);

      return null;

    }

    final uri = Uri.parse('http://192.168.10.10:3000/api/v1/admin/upload'); // change to your local server URL

    final request = http.MultipartRequest('POST', uri)

      ..files.add(http.MultipartFile.fromBytes(

        'file', // match this key with your backend's expected field

        file.bytes!,

        filename: file.name,

        contentType: MediaType('image', file.extension ?? 'jpg'),

      ));

    final response = await request.send();

    if (response.statusCode == 200) {

      final respStr = await response.stream.bytesToString();

      final decoded = jsonDecode(respStr);

      if (decoded['url'] != null) {

        showSnackBar(message: "Image uploaded!", type: SnackBarType.success);

        return decoded['url']; // return the URL to save in DB

      } else {

        showSnackBar(message: "Upload failed", type: SnackBarType.error);

        return null;

      }

    } else {

      showSnackBar(message: "Upload failed: ${response.statusCode}", type: SnackBarType.error);

      return null;

    }

  } catch (e, s) {

    logger.e(e, stackTrace: s);

    showSnackBar(message: 'Failed to upload image', type: SnackBarType.error);

    return null;

  }

}

So we are passing the PlatformFile and then this calls the backend server and upload the image. Then we see we have url is returned. Now this url could be used in the NetworkImage.

Buy the flutter web app admin panel

Comment

Add Reviews