简体   繁体   中英

Is it possible to show progress bar when upload image via http flutter?

I am working on an app that uploads an image to Amazon S3 bucket , and instead of just showing a Spinner , I'd love to be able to get Progress on the status of that upload.

I am uploading a file using MultipartRequest from Package:http . I am successfully uploading the file but I want to get the Progress of the file that is being uploaded. How can I achieve that? My current code looks something like this.

  static Future<bool> uploadFile({@required userId, @required albumId, @required data, @required fileName}) async{

    const _accessKeyId = 'AKIAVV**********';
    const _secretKeyId = 'iyBmdn6v***************************';
    const _region = 'us-east-1';
    const _s3Endpoint = 'https://myalbums-content.s3.amazonaws.com';

    final file = data;
    var stream = new http.ByteStream(DelegatingStream.typed(file.openRead()));
    final length = await file.length();

    final uri = Uri.parse(_s3Endpoint);
    final req = http.MultipartRequest("POST", uri);

    var multipartFile =  http.MultipartFile('file', stream, length,
       contentType: new MediaType('image','JPG'));

    final policy = Policy.fromS3PresignedPost(userId.toString() +'/'+ albumId.toString() +'/'+ fileName,
        'myalbums-content', _accessKeyId, 15, length, region: _region);

    final key = SigV4.calculateSigningKey(_secretKeyId, policy.datetime, _region, 's3');
    final signature = SigV4.calculateSignature(key, policy.encode());
    
    req.files.add(multipartFile);
    req.fields['key'] = policy.key;
    req.fields['acl'] = 'public-read';
    req.fields['X-Amz-Credential'] = policy.credential;
    req.fields['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256';
    req.fields['X-Amz-Date'] = policy.datetime;
    req.fields['Policy'] = policy.encode();
    req.fields['X-Amz-Signature'] = signature;

    try {
      final res = await req.send();

      if(res.statusCode == 204){
        return true;
      } else {
        return false;
      }
    } catch (e) {
      print('Network issue: '+e.toString());
      return false;
    }
  }

Thank you in advance.

Check out this example on Github. It shows how you can upload the file using a Stream. If you expose the stream of bytes uploaded to your Widget, you should be able to use a ProgressIndicator that compares the total number of bytes to the value in the Stream.

static Future<String> fileUploadMultipart(
      {File file, OnUploadProgressCallback onUploadProgress}) async {
    assert(file != null);

    final url = '$baseUrl/api/file';

    final httpClient = getHttpClient();

    final request = await httpClient.postUrl(Uri.parse(url));

    int byteCount = 0;

    var multipart = await http.MultipartFile.fromPath(fileUtil.basename(file.path), file.path);

    // final fileStreamFile = file.openRead();

    // var multipart = MultipartFile("file", fileStreamFile, file.lengthSync(),
    //     filename: fileUtil.basename(file.path));

    var requestMultipart = http.MultipartRequest("", Uri.parse("uri"));

    requestMultipart.files.add(multipart);

    var msStream = requestMultipart.finalize();

    var totalByteLength = requestMultipart.contentLength;

    request.contentLength = totalByteLength;

    request.headers.set(
        HttpHeaders.contentTypeHeader, requestMultipart.headers[HttpHeaders.contentTypeHeader]);

    Stream<List<int>> streamUpload = msStream.transform(
      new StreamTransformer.fromHandlers(
        handleData: (data, sink) {
          sink.add(data);

          byteCount += data.length;

          if (onUploadProgress != null) {
            onUploadProgress(byteCount, totalByteLength);
            // CALL STATUS CALLBACK;
          }
        },
        handleError: (error, stack, sink) {
          throw error;
        },
        handleDone: (sink) {
          sink.close();
          // UPLOAD DONE;
        },
      ),
    );

    await request.addStream(streamUpload);

    final httpResponse = await request.close();
//
    var statusCode = httpResponse.statusCode;

    if (statusCode ~/ 100 != 2) {
      throw Exception('Error uploading file, Status code: ${httpResponse.statusCode}');
    } else {
      return await readResponseAsString(httpResponse);
    }
  }

req.send also returns a StreamedResponse which may be easier to implement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM