Error when trying to upload image to BaasBox



  • Hi, I'm trying to upload an image to a BaasBox backend. The endpoint receive data in the following form:

    curl -X POST http://localhost:9000/file \
    -F file=@test.jpg \
    -H X-BB-SESSION:9952384d-8d78-4399-82d0-7039f832a786
    

    I try to upload the image using these three methods:

    void Rest::iniciar(QString url)
    {
    estatusRespuesta = false;
    
    peticion.setUrl(QUrl(url));
    peticion.setHeader(peticion.ContentTypeHeader,"application/json");
    peticion.setRawHeader(QByteArray("X-BAASBOX-APPCODE"), QByteArray(llave.toStdString().c_str()));
    }
    
    bool Rest::crearCabeceraMultiparte(QString url)
    {
    multiparte = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    
    QHttpPart parteArchivo;
    
    //parteArchivo.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
    parteArchivo.setHeader(QNetworkRequest::ContentDispositionHeader,
    QVariant("form-data; name=\"file\""));
    
    QFile* imagen = new QFile(url);
    
    if(imagen->open(QIODevice::ReadOnly))
    {
    parteArchivo.setBodyDevice(imagen);
    imagen->setParent(multiparte);
    multiparte->append(parteArchivo);
    return true;
    }
    else
    {
    qDebug()<< imagen->errorString();
    }
    
    return false;
    }
    
    void Rest::postArchivo()
    {
    respuestaBruta = manejadorConexion->post(peticion, multiparte);
    multiparte->setParent(respuestaBruta);
    qDebug()<<"Enviando Post";
    
    connect(respuestaBruta, SIGNAL(finished()), this, SLOT(respuestaRecibida()));
    //multiparte->deleteLater();
    

    }

    But I get this error when the backend response:

    Error del Endpoint: QNetworkReply::NetworkError(ProtocolInvalidOperationError)
    "Vary" : "Accept-Encoding"
    "Content-Encoding" : "gzip"
    "Content-Type" : "application/json; charset=utf-8"
    

  • Lifetime Qt Champion

    Hi,

    It seems the headers are not matching between your curl sample and your peticion object settings. The first one has X-BB-SESSION while the other one as X-BAASBOX-APPCODE.

    By the way, if llave is a QString, you can use .toLatin1() rather than doing that conversion.



  • I update my code and it still give me the same error. the code is the following:

    QString url = "http://127.0.0.1:9000/file";
        QString campo = "X-BB-SESSION";
        QString valor = "codigo usuario";
        estatusRespuesta = false;
    
        peticion.setUrl(QUrl(url));
        peticion.setRawHeader(QByteArray("X-BAASBOX-APPCODE"), QByteArray(llave.toStdString().c_str()));
        peticion.setRawHeader(QByteArray(campo.toStdString().c_str()), QByteArray(valor.toStdString().c_str()));
        QFile* imagen = new QFile(url);
    
        if(imagen->open(QIODevice::ReadOnly))
        {
            QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
            QHttpPart parteArchivo;
            parteArchivo.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
            parteArchivo.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\""));
            parteArchivo.setBodyDevice(imagen);
            imagen->setParent(multiPart);
            multiPart->append(parteArchivo);
    
    
    
            respuestaBruta = manejadorConexion->post(peticion, multiPart);
            connect(respuestaBruta, SIGNAL(finished()), this, SLOT(respuestaRecibida()));
    
            multiPart->setParent(respuestaBruta);
            qDebug()<<"Enviando Post";
    
            return true;
        }
        else
        {
            qDebug()<< imagen->errorString();
        }
    
    

  • Lifetime Qt Champion

    Did you try to look for the exact content of the request you send ?
    How does it compare to the curl call ?

    On a side note, rather than doing these multiple conversions that are rather useless, change the type of your variables to be QByteArray directly.



  • @SGaist said in Error when trying to upload image to BaasBox:
    Hi, thanks for your reply and sorry for my late one.
    I made some changes in my code and now BaasBox save the file I upload, but doesn't recognize what kind of file I'm uploading.
    The actual code that make the post is

     archivo = new QFile(url);
        QFileInfo informacionArchivo(url);
    
        if(archivo->open(QIODevice::ReadOnly))
        {
    
            multiParte = new QHttpMultiPart(QHttpMultiPart::FormDataType);
            QHttpPart parteArchivo;
            parteArchivo.setHeader(QNetworkRequest::ContentDispositionHeader,
                                   QVariant("form-data; name=\"name\"; filename=\""+informacionArchivo.fileName()+"\";\r\n"));
            parteArchivo.setHeader(QNetworkRequest::ContentTypeHeader, "image/"+informacionArchivo.suffix().toUpper().toLatin1() );
    
            parteArchivo.setBodyDevice(archivo);
            archivo->setParent(multiParte);
            multiParte->append(parteArchivo);
    
            respuestaBruta = manejadorConexion->post(peticion, multiParte);
            connect(respuestaBruta, SIGNAL(finished()), this, SLOT(respuestaRecibida()));
    
            multiParte->setParent(respuestaBruta);
            qDebug()<<"Enviando Post";
    
            return true;
        }
        else
        {
            qDebug()<< archivo->errorString();
    
        }
    

    and Baasbox response with:

    "Vary" : "Accept-Encoding"
    "Access-Control-Allow-Origin" : "*"
    "Access-Control-Allow-Headers" : "X-Requested-With"
    "Content-Encoding" : "gzip"
    "Content-Type" : "application/json; charset=utf-8"
    "Date" : "Mon, 11 Dec 2017 18:54:42 GMT"
    "BB-USERNAME" : "admin"
    "{\"result\":\"ok\",\"data\":{\"@version\":2,\"_creation_date\":\"2017-12-11T14:54:41.903-0400\",\"id\":\"383e5f4e-d393-449d-94d8-055917afd3b6\",\"_author\":\"admin\",\"fileName\":\"2e8f7c8c35a5615fcf295159fcdc00b9.jpg\",\"contentType\":\"image/jpeg\",\"contentLength\":26566,\"metadata\":{\"@version\":1,\"X-Parsed-By\":[\"org.apache.tika.parser.DefaultParser\",\"org.apache.tika.parser.jpeg.JpegParser\"],\"_bb_parser_version\":\"1.0.0-M3-20160325\",\"_bb_parser_exception\":\"org.apache.tika.exception.TikaException: Can't read JPEG metadata\\u000a\\u0009at org.apache.tika.parser.image.ImageMetadataExtractor.parseJpeg(ImageMetadataExtractor.java:100)\\u000a\\u0009at org.apache.tika.parser.jpeg.JpegParser.parse(JpegParser.java:56)\\u000a\\u0009at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:256)\\u000a\\u0009at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:256)\\u000a\\u0009at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:120)\\u000a\\u0009at com.baasbox.controllers.File.lambda$storeFile$160(File.java:256)\\u000a\\u0009at com.baasbox.db.DbHelper.lambda$withDbFromContext$267(DbHelper.java:876)\\u000a\\u0009at play.core.j.FPromiseHelper$$anonfun$promise$2.apply(FPromiseHelper.scala:34)\\u000a\\u0009at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24)\\u000a\\u0009at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24)\\u000a\\u0009at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:37)\\u000a\\u0009at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:42)\\u000a\\u0009at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386)\\u000a\\u0009at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)\\u000a\\u0009at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)\\u000a\\u0009at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)\\u000a\\u0009at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)\\u000aCaused by: com.drew.imaging.jpeg.JpegProcessingException: not a jpeg file\\u000a\\u0009at com.drew.imaging.jpeg.JpegSegmentReader.readSegments(JpegSegmentReader.java:215)\\u000a\\u0009at com.drew.imaging.jpeg.JpegSegmentReader.<init>(JpegSegmentReader.java:107)\\u000a\\u0009at com.drew.imaging.jpeg.JpegMetadataReader.readMetadata(JpegMetadataReader.java:70)\\u000a\\u0009at org.apache.tika.parser.image.ImageMetadataExtractor.parseJpeg(ImageMetadataExtractor.java:97)\\u000a\\u0009... 16 more\\u000a\",\"resourceName\":\"2e8f7c8c35a5615fcf295159fcdc00b9.jpg\",\"Content-Type\":\"image/jpeg\",\"_bb_parser_error\":\"TikaException: Can't read JPEG metadata\"},\"attachedData\":{}},\"http_code\":201}"
    

  • Lifetime Qt Champion

    Did you try to follow more closely the example provided in the details of QHttpMultiPart ?



  • Yes, I followed that page to write my code, but I had to add

    filename=\""+informacionArchivo.fileName()+"\";\r\n"
    

    to the QHttpPart.setHeader method.
    It seems that Baasbox can't read the file metadata and fails to identify the type of the file.
    I try to upload my file in QByteArray form but QHttpPart.setBodyDevice only take a QIODevice object as parameter.
    Is there any other way to upload a file to a server with a post method using qt?


  • Lifetime Qt Champion

    You can use a QBuffer but AFAIK it shouldn't change anything.



  • Thanks for your answer.
    At last I found the solution and I would like to share it. I had to change this line

    parteArchivo.setHeader(QNetworkRequest::ContentDispositionHeader,
    QVariant("form-data; name="name"; filename=""+informacionArchivo.fileName()+"";\n"));

    at the end of the header I put \r\n at the end. I just remove the return of car and the backend recognize the file metadata


  • Lifetime Qt Champion

    Glad you found out and thanks for sharing !



  • Thanks to all.
    The problem was solved


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.