1. 程式人生 > >Qt Http QHttpMultiPart上傳檔案到java http伺服器

Qt Http QHttpMultiPart上傳檔案到java http伺服器

                         Qt Http QHttpMultiPart上傳檔案到java http伺服器

1.最近專案用到了Qt上傳檔案到HTTP伺服器,由於之前做過一個http接收檔案的伺服器,所以直接拿來除錯。由於對http的瞭解一個不夠深入,除錯了許久都沒有成功上傳檔案到伺服器。之前是寫的伺服器一直是用網頁的方式和postman來模仿post檔案。

由於找不到失敗的原因,所以直接用wareshark來抓包看一下Qt post的資料和網頁上傳有什麼區別。在第4.節圖中給出了網頁上傳檔案時wareshark抓取到的資料包。

2.經過除錯後可用的Qt  程式碼,由於我的http是在多執行緒中使用,所以在此處加入了一個QEventLoop來同步等待返回上傳結果。

void HttpObject::uploadFile()
{
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QString path = QString("/home/maowendi/Desktop/image.jpg");
    QHttpPart imagePart;
    imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"image.jpg\""));
    imgFile = new QFile(path);
    imgFile->open(QIODevice::ReadOnly);
    imagePart.setBodyDevice(file);
    imgFile->setParent(multiPart); 
    multiPart->append(imagePart);
    QUrl url("http://172.20.149.148:8089/upload-file");
    QNetworkRequest request(url);

    uploadFileReply = m_httpNAM->post(request, multiPart);
    multiPart->setParent(uploadFileReply); 
    connect(uploadFileReply,SIGNAL(finished()),this,SLOT(httpUploadFinished()));
    QEventLoop eventLoop;
    connect(m_httpNAM, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
    eventLoop.exec();       
}

void HttpObject::httpUploadFinished()  
{
   if(uploadFileReply->error() == QNetworkReply::NoError) {
    qDebug()<<"upload file finished";
    imgFile->flush();
    imgFile->close();
    uploadFileReply->deleteLater();
    uploadFileReply = NULL;
    delete imgFile;
    imgFile = NULL;
   }
   else
   {
        qDebug()<<"error string:"<<uploadFileReply->errorString();
        uploadFileReply->deleteLater();
   }

}

 

3.Qt官方例程的程式碼如下,根據官方例程還是要做一點修改才能成功上傳檔案的。

其中紅色框部分根據我自己的java伺服器測試抓包資料進行了修改。見下圖

4.抓包工具Wareshark,抓取資料包如下

5.結果執行程式碼後伺服器返回成功

6.Java伺服器處理接收檔案程式碼

   /**
     * 上傳單個檔案`      1
     *
     * @param file 上傳檔案 MultipartFile 的物件
     * @return 上傳的結果
     */
    @RequestMapping(value = "/upload-file", method = RequestMethod.POST)
    @ResponseBody
    public String uploadFile(HttpServletRequest request,@RequestParam("file") MultipartFile file) {
        saveFile(file);
        System.out.println(filePath);

        ReturnWeb ret = new ReturnWeb();
        ret.setCode(1);
        ret.setCount(0);
        ret.setMsg("Success");
        JSONObject jsonS = (JSONObject) JSON.toJSON(ret);
        return jsonS.toString();
    }
  /**
     * 把 HTTP 請求中的檔案流儲存到本地
     *
     * @param file MultipartFile 的物件
     */
    private boolean saveFile(MultipartFile file) {
        if (!file.isEmpty()) {
            try {
                // getRealPath() 取得 WEB-INF 所在資料夾路徑
                // 如果引數是 "/temp", 當 temp 存在時返回 temp 的本地路徑, 不存在時返回 null/temp (無效路徑)
                //String path ="D:\\IDEAPro\\File"+ File.separator + file.getOriginalFilename();;
                String path =servletContext.getRealPath("") + File.separator + file.getOriginalFilename();
                FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(path));
                fileName = file.getOriginalFilename();
                filePath = "http://172.20.149.148:8089/"+fileName;
                return true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }