英文:
Go http: no such file after sending image from Qt client
问题
我有一个Go API,应该保存客户端发送的图像。我知道当POST请求来自HTML表单时,Go代码是有效的。然而,当我从我的Qt C++客户端发送一个多部分的POST请求时,服务器返回一个错误:
> http: no such file
在客户端,我有一个QPixmap,我将其转换为QByteArray,然后发送,但是不知何故我从Go那里得到了这个错误。我知道当我移除
multi_part->append(image_part);
时,客户端发送的数据长度减少,所以应该是QPixmap被发送了。
Go代码:
func apiUploadHandler(w http.ResponseWriter, req *http.Request) {
if req.Method == "POST" {
req.ParseMultipartForm(0)
fmt.Printf("%v %v %v", req.RemoteAddr, req.ContentLength, req.Body)
file, fileheader, err := req.FormFile("image")
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
defer file.Close()
var id string
created := false
for created != true {
id = generateImageID()
err = db.CheckIfImageIDInUse(id)
if err != nil {
if err.Error() == "Image ID '"+id+"' exists.'" {
created = false
continue
} else {
created = false
cio.PrintMessage(1, err.Error())
return
}
}
created = true
}
filePath := fsys.ImgStoragePath + id + "." + strings.Split(fileheader.Filename, ".")[1]
err = db.StoreImage(id, strings.Split(fileheader.Filename, ".")[0] /*image name*/, filePath, strings.Split(fileheader.Filename, ".")[1] /*extension*/)
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
bytesCopied, err := fsys.StoreImage(filePath, file)
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
cio.PrintMessage(0, "File "+filePath+" has been created.")
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
cio.PrintMessage(0, "Content of uploaded image ("+strconv.FormatInt(bytesCopied, 10)+" Bytes) has been copied to "+filePath+".")
http.Redirect(w, req, "/"+id, http.StatusFound)
}
}
Qt C++客户端代码:
void Share::upload(const QByteArray &data) {
QHttpMultiPart *multi_part = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart text_part;
text_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
text_part.setBody("Screenshot.png");
QHttpPart image_part;
image_part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
image_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
image_part.setBody(data);
multi_part->append(text_part);
multi_part->append(image_part);
QNetworkRequest request(QUrl("http://localhost:8000/api/upload"));
QNetworkAccessManager *manager = new QNetworkAccessManager();
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(reply_finished(QNetworkReply *)));
manager->post(request, multi_part);
qDebug() << QString(data);
}
英文:
I have a Go API that should save an image sent by a client. I know that the Go code works when the POST request comes from a HTML form.
When sending a multipart post request from my Qt C++ client though, the server returns an error
> http: no such file
On the client side I have a QPixmap, which I transform to a QByteArray, which I then send, but somehow I get that error from Go. I know that the length of the data sent by the client decreases when I remove
multi_part->append(image_part);
so the QPixmap should be sent.
Go code:
func apiUploadHandler(w http.ResponseWriter, req *http.Request) {
if req.Method == "POST" {
req.ParseMultipartForm(0)
fmt.Printf("%v %v %v", req.RemoteAddr, req.ContentLength, req.Body)
file, fileheader, err := req.FormFile("image")
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
defer file.Close()
var id string
created := false
for created != true {
id = generateImageID()
err = db.CheckIfImageIDInUse(id)
if err != nil {
if err.Error() == "Image ID '"+id+"' exists.'" {
created = false
continue
} else {
created = false
cio.PrintMessage(1, err.Error())
return
}
}
created = true
}
filePath := fsys.ImgStoragePath + id + "." + strings.Split(fileheader.Filename, ".")[1]
err = db.StoreImage(id, strings.Split(fileheader.Filename, ".")[0] /*image name*/, filePath, strings.Split(fileheader.Filename, ".")[1] /*extension*/)
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
bytesCopied, err := fsys.StoreImage(filePath, file)
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
cio.PrintMessage(0, "File "+filePath+" has been created.")
if err != nil {
cio.PrintMessage(1, err.Error())
return
}
cio.PrintMessage(0, "Content of uploaded image ("+strconv.FormatInt(bytesCopied, 10)+" Bytes) has been copied to "+filePath+".")
http.Redirect(w, req, "/"+id, http.StatusFound)
}
}
Qt C++ client code:
void Share::upload(const QByteArray &data) {
QHttpMultiPart *multi_part = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart text_part;
text_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\"\""));
text_part.setBody("Screenshot.png");
QHttpPart image_part;
image_part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
image_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
image_part.setBody(data);
multi_part->append(text_part);
multi_part->append(image_part);
QNetworkRequest request(QUrl("http://localhost:8000/api/upload"));
QNetworkAccessManager *manager = new QNetworkAccessManager();
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(reply_finished(QNetworkReply *)));
manager->post(request, multi_part);
qDebug() << QString(data);
}
答案1
得分: 1
我不确定,但你可以尝试将以下代码部分进行更改:
image_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
更改为以下内容:
image_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\"; filename=\"Screenshot.png\""));
这样可能会起到你想要的效果。
英文:
I'm not sure but you can try to change
image_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
to something like
image_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\"; filename=\"Screenshot.png\""));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论