skip to Main Content

I want to create a file directory for my Flutter mobile application and upload files (any kind of images or pdf files).

I use the following code for selecting and uploading the file to the server :

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:file_picker/file_picker.dart';

class fileUpload extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UploadScreen(),
    );
  }
}

class UploadScreen extends StatefulWidget {
  @override
  _UploadScreenState createState() => _UploadScreenState();
}

class _UploadScreenState extends State<UploadScreen> {
  File? _selectedFile;

  Future<void> _selectFile() async {
    FilePickerResult? result = await FilePicker.platform.pickFiles();

    if (result != null) {
      setState(() {
        _selectedFile = File(result.files.single.path!);
      });
    }
  }

  Future<void> _uploadFile() async {
    if (_selectedFile == null) {
      print('no files picked');
      return;
    }

    var uri = Uri.parse('http://myhostingdomain.com/specialdirectory'); // Sunucunun URL'si

    var request = http.MultipartRequest('POST', uri);
    request.files.add(await http.MultipartFile.fromPath('file', _selectedFile!.path));

    var response = await request.send();
    if (response.statusCode == 200) {
      print('successfully uploaded.');
    } else {
      print('Error returned: ${response.reasonPhrase}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Sample file upload page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _selectFile,
              child: Text('Choose a file'),
            ),
            SizedBox(height: 20),
            _selectedFile != null
                ? Text('selected file: ${_selectedFile!.path}')
                : Text('no files found'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _uploadFile,
              child: Text('upload the file'),
            ),
          ],
        ),
      ),
    );
  }
}

When I run my mobile application everything looks file and file seems uploaded. But when I check the file server at the hosting destination, there is no file uploaded.

I believe I have to configure the public hosting server and send the authentication before I start the uploading the file.

How should I update my code to add the credentials while connecting the destination and additionally how should I configure the hosting server to accept uploadings?

Thank you

there are several solutions I found over internet but not including the credentials for a public hosting server.

2

Answers


  1. Chosen as BEST ANSWER

    I have noticed that writing a file (by uploading) directly to a remote server requires a lot of security constraints. If we remove the security constraints the zone (target directory) at the remote server becomes weak. That's why many solutions offer creating an interface to upload a file to the server. Such as a web page or webapi.

    I have created the following webapi app in python to get the file and write to the server.

    @app.route('/api/uploadafile', methods=['GET','POST'])
    def uploadtheFile():
    if 'myfile' not in request.files:
        return 'file could not be uploaded.', 400
    
    myfile = request.files['myfile']
    if myfile.filename == '':
        return 'please specify the filename', 400
    
    
    myfile.save('dirforReceivedfiles/' + myfile.filename)
    
    return 'successfully uploaded', 200
    

    then I call this api from my flutter application :

     Future<void> uploadthisFile(File myfile) async {
     var url = Uri.parse('http://remoteaddress:<port>/api/uploadfile'); //   Flask web API URL
    
     var stream = new http.ByteStream(myfile.openRead());
     var mylength = await myfile.length();
    
     var request = new http.MultipartRequest('POST', url);
     var multipartFile = new http.MultipartFile('myfile', stream, mylength,
      filename: path.basename(myfile.path));
    
     request.files.add(multipartFile);
    
     var response = await request.send();
     if (response.statusCode == 200) {
       print('Successfully uploaded');
     } else {
     print('Failed! Error is: ${response.statusCode}');
     }
     }
    

    I tested this code above and successfully worked for both local and remote (hosting) servers.

    You have to be careful for the following points :

    1- the webapi is hosted and running at the remote server. Python webapi using flask, must be run at Apache or NGINX, doesn't work on IIS directly.

    2- the directory (e.g. /receivedfiles ) must be accessbile for the webapi application at the remote server.

    3- the file type and file size must be configured at the flutter (dart) code before sending. If you remove the constraints (limits), you are most likely receive weird error messages that you can see at server logs.


  2. Uploading a file is a multi-step process that requires work on the client and server side:

    Server Side:

    Create a folder to save your uploaded files. Make sure the folder is in your website directory and you can call it something like: UploadsFolder

    For this example, I am using localhost.

    Write the following code into a php file and call it uploadData.php

    <?php
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        try {
    
            // File handling
            $file = $_FILES['file'];
            $fileName = $file['name'];
            $fileTmpName = $file['tmp_name'];
            
    
            // Move the uploaded file to the desired directory
            $uploadsDirectory = 'UploadsFolder/';
            $targetPath = $uploadsDirectory . $fileName;
    
            move_uploaded_file($fileTmpName, $targetPath);
    
      
        } catch (Exception $e) {
            http_response_code(500); // Internal Server Error
        } 
    }
    ?>
    

    Client side:

    write the following commands in your terminal to install the http and file_picker packages in flutter:

    flutter pub add http
    flutter pub add file_picker

    Use the following code to upload your file

    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:file_picker/file_picker.dart';
    import 'package:http/http.dart' as http;
    import 'package:http/http.dart';
    void main()=>runApp(const MyApp());
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          home: Scaffold(
            body: 
            Center(child:
            FileUploader()
          )),
        );
      }
    }
    // as widgets
    
    class FileUploader extends StatefulWidget {
      const FileUploader({super.key});
      @override
      State<FileUploader> createState() => _FileUploaderState();
    }
    
    class _FileUploaderState extends State<FileUploader> {
    String? fileName;
    PlatformFile? selectedFile;
    
    Future<void> _uploadFile() async {
        if (selectedFile == null) {
          print('no files picked');
          return;
        }
    
        var uri = Uri.parse('http://10.0.2.2/demoProject/uploadData.php'); // Sunucunun URL'si
    
        var request = http.MultipartRequest('POST', uri);
        request.files.add(await http.MultipartFile.fromPath('file', selectedFile!.path??""));
    
        var response = await request.send();
        if (response.statusCode == 200) {
          print('successfully uploaded.');
        } else {
          print('Error returned: ${response.reasonPhrase}');
        }
      }
    
    
    
    pickFile() async {
        FilePickerResult? result = await FilePicker.platform.pickFiles();
        if (result != null) {
          PlatformFile? file = result.files.first;
        setState(() {
          selectedFile=file;
          fileName=file.name;
    print("fileName is $fileName");
        });
        }
        return null;
      }  
      
      @override
      Widget build(BuildContext context) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
          
    ElevatedButton(onPressed: () async {
    await pickFile();
    
    
    }, child: const Text("Pick file to upload")),
    
    ElevatedButton(onPressed: ()async{
    if(selectedFile!=null){
        
    await _uploadFile();
    }
    }, child: const Text("Upload selected file"))
    
        ],);
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search