У меня есть следующий PHP-скрипт, для которого я отправляю POST, чтобы загрузить файлы на мой сервер:
<?php
$allowedExts = array("gif", "jpeg", "jpg", "png", "txt");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/jpg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/x-png")
|| ($_FILES["file"]["type"] == "image/png")
|| ($_FILES["file"]["type"] == "text/plain"))
&& ($_FILES["file"]["size"] < 20000)
&& in_array($extension, $allowedExts))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br>";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br>";
echo "Type: " . $_FILES["file"]["type"] . "<br>";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}
}
}
else
{
echo "Invalid file";
}
?>
И мой друг использует этот код C++ для изображений POST на сервере:
void CNetworkManager::doUpload(const QUrl& url, QString fileName)
{
QString path(fileName);
QNetworkRequest request(url);
QString bound="margin";
QByteArray data(QString("--" + bound + "\r\n").toLatin1());
data.append("Content-Disposition: form-data; name=\"action\"\r\n\r\n");
data.append(url.toString() + "\r\n");
data.append("--" + bound + "\r\n");
data.append("Content-Disposition: form-data; name=\"file\"; filename=\"://resources/images/heart.png\"\r\n");
data.append("Content-Type: image/png\r\n\r\n");
QFile file(path);
if (!file.open(QIODevice::ReadOnly))
return;
data.append(file.readAll());
data.append("\r\n");
data.append("--" + bound + "--\r\n");
request.setRawHeader(QString("Content-Type").toLatin1(),QString("multipart/form-data; boundary=" + bound).toLatin1());
request.setRawHeader(QString("Content-Length").toLatin1(), QString::number(data.length()).toLatin1());
_uploadManager.post(request,data);
}
И я пытаюсь имитировать его в Objective-C, поэтому я могу сделать то же самое в приложении Mac и загрузить файлы txt:
NSString *url = @"";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
request.HTTPMethod = @"POST";
NSString *boundary = @"ghfd67df7gsfd67676gasgd";
NSString *headerFieldValue = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request addValue:headerFieldValue forHTTPHeaderField:@"Content-Type"];
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:@"%@/textfile.txt", documentsDirectory];
NSString *content = @"Lorem ipsum dolor sit amet.";
[content writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];
NSMutableData *postData = [[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding] mutableCopy];
[postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"action\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[[NSString stringWithFormat:@"%@\r\n", url] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[@"Content-Type: text/plain\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[postData appendData:[[NSFileManager defaultManager] contentsAtPath:fileName]];
[postData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = postData;
[request addValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"%@", response);
}];
Но по какой-то причине это не работает. Я попытался преобразовать операторы C++ в их сопоставления Objective-C, но файл никогда не появляется на сервере.
Что я делаю не так?
Ваш код выше работает правильно, проблема в том, что вы не назвали поле формы правильно.
[postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
В этой строке указано имя поля формы в качестве файла userfile
, а код C++:
data.append("Content-Disposition: form-data; name=\"file\"; filename=\"://resources/images/heart.png\"\r\n");
перечисляет поле формы в виде file
. Это вызовет проблему при загрузке, поскольку сервер ожидает имя file
именем, а не file
userfile
.