PHP:将文件从一台服务器上传到另一台服务器

时间:2016-02-10 09:19:43

标签: post curl file-upload

我在服务器上开发一个网站,而存储在另一台服务器上,我不得不以某种方式处理它。我亲身经历这种情况,我发现解决方案是使用curl。

请向我解释如何从零开始详细使用Curl。

更新

我使用以下代码测试是否已安装并启用cURL:

<?PHP
phpinfo(); 

$toCheckURL = "http://board/accSystem/webroot/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $toCheckURL);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
$data = curl_exec($ch);
curl_close($ch);
preg_match_all("/HTTP\/1\.[1|0]\s(\d{3})/",$data,$matches);
$code = end($matches[1]);
if(!$data) {
  echo "Domain could not be found";
} else {
  switch($code) {
    case '200':
      echo "Page Found";
      break;
    case '401':
      echo "Unauthorized";
      break;
    case '403':
      echo "Forbidden";
      break;
    case '404':
      echo "Page Not Found";
      break;
    case '500':
      echo "Internal Server Error";
      break;
  }
}
?>

结果如下: enter image description here

我收到了(Page found)消息

现在我可以毫无顾虑地使用cURL吧?

注意: 两台服务器都是本地的

7 个答案:

答案 0 :(得分:16)

作为一名PHP开发人员,您可能已经熟悉PHP最方便的文件系统函数fopen。该函数打开一个文件流并返回一个资源,然后可以将该资源传递给fread或fwrite来读取或写入数据。有些人没有意识到文件资源不一定必须指向本地计算机上的位置。

以下是将文件从本地服务器传输到ftp服务器的示例:

library(data.table)
setDT(df1)[, A1:= (A-1)%/%2 +1][, 
  list(A= paste0("A",paste(unique(A), 
             collapse="-")), B= sum(B)) ,A1][,A1:= NULL][]
#      A B
#1: A1-2 4
#2: A3-4 9

支持的不同协议列表可以在PHP手册的附录M中找到。您可能希望使用一种采用某种加密机制(如FTPS或SSH)的协议,具体取决于网络设置和您正在移动的信息的敏感性。

curl扩展使用客户端URL库(libcurl)来传输文件。实现卷曲解决方案的逻辑通常如下:首先初始化会话,设置所需的传输选项,执行传输然后关闭会话。

使用curl_init函数初始化curl会话。该函数返回一个可以与其他curl函数一起使用的资源,就像在文件系统函数中使用fopen获取资源一样。

使用curl_setopt设置上传目的地和传输会话的其他方面,curl_setopt接受curl资源,一个表示设置和选项值的预定义常量。

以下是使用HTTP协议的PUT方法将文件从本地主机传输到远程服务器的示例:

$file = "filename.jpg";
$dest = fopen("ftp://username:password@example.com/" . $file, "wb");
$src = file_get_contents($file);
fwrite($dest, $src, strlen($src));
fclose($dest); 

可以在php文档中找到curl的有效选项列表。

ftp扩展允许您实现对ftp服务器的客户端访问。当前两个选项可用时,使用ftp传输文件可能有点过头了...理想情况下,最好使用此扩展名,需要更高级的功能。

使用ftp_connect与ftp服务器建立连接。您可以使用ftp_login通过提供用户名和密码来验证与ftp服务器的会话。使用ftp_put函数将文件放在远程服务器上。它接受目标文件名的名称,本地源文件名和预定义常量以指定传输模式:FTP_ASCII用于纯文本传输,FTP_BINARY用于二进制传输。传输完成后,ftp_close用于释放资源并终止ftp会话。

$file = "testfile.txt";

$c = curl_init();
curl_setopt($c, CURLOPT_URL, "http://example.com/putscript");
curl_setopt($c, CURLOPT_USERPWD, "username:password");
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_PUT, true);
curl_setopt($c, CURLOPT_INFILESIZE, filesize($file));

$fp = fopen($file, "r");
curl_setopt($c, CURLOPT_INFILE, $fp);

curl_exec($c);

curl_close($c);
fclose($fp); 

答案 1 :(得分:4)

我们正在使用与您相同的用例。我们有两个服务器:应用服务器和存储服务器。应用服务器包含方法和UI部分,存储服务器是我们上传文件的地方。以下是我们用于文件上传的,正常工作:

1)您必须在存储服务器上添加一个包含以下方法的php文件:

<?php
switch ($_POST['calling_method']) {    
case 'upload_file':
    echo uploadFile();
    break;
case 'delete':
    return deleteFile();
    break;    
}

function uploadFile() {
   $localFile = $_FILES['file']['tmp_name'];

   if (!file_exists($_POST['destination'])) {
     mkdir($_POST['destination'], 0777, true);
   }

   $destination = $_POST['destination'] . '/' . $_FILES['file']['name'];
   if (isset($_POST['file_name'])) {
      $destination = $_POST['destination'] . '/' . $_POST['file_name'];
   }
   $moved = move_uploaded_file($localFile, $destination);

   if (isset($_POST['file_name'])) {
    chmod($destination, 0777);
   }
   $result['message'] = $moved ? 'success' : 'fail';
   echo json_encode($result);
 }

function deleteFile() {
   if (file_exists($_POST['file_to_be_deleted'])) {
     $res = unlink($_POST['file_to_be_deleted']);
     return $res;
   }
  return FALSE;
}
?>

2)在您的应用程序服务器上。

创建一个将$ _FILES数据传递给存储服务器的方法。

 $data = array(
    'file' => new CURLFile($_FILES['file']['tmp_name'],$_FILES['file']['type'], $_FILES['file']['name']),
    'destination' => 'destination path in which file will be uploaded',
    'calling_method' => 'upload_file',
    'file_name' => 'file name, you want to give when upload will completed'
); 

**Note :CURLFile class will work if you have PHP version >= 5**

 $ch = curl_init();

curl_setopt($ch, CURLOPT_URL, PATH_FOR_THAT_PHP_FILE_ON_STORAGE_SERVER_FILE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_TIMEOUT, 86400); // 1 Day Timeout
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60000);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_HOST']);

$response = curl_exec($ch);
if (curl_errno($ch)) {

    $msg = FALSE;
} else {
    $msg = $response;
}

curl_close($ch);
echo $msg;

通过这种方式使用CURL,它将调用存储服务器文件方法并上传文件,同样可以调用方法删除文件。

希望这会有所帮助。

答案 2 :(得分:2)

首先,抱歉我的英语不好 我创建了另一种方法,不使用 cURL 并使用 POST

uploader.php

<form method="POST" action="//uploadfile.php" enctype="multipart/form-data">
// SETS THE MAX FILE SIZE (in bytes)
   <input type="hidden" name="MAX_FILE_SIZE" value="2097152" />
// SETS THE FILE NAME
   <input type="hidden" name="nam"    value="myfile" />
// SETS THE FOLDER NAME
   <input type="hidden" name="f"      value="ups" /><br>
// SETS THE RETURN PAGE NOTE: the file will return on the end, so will be view.php?img=myfile.png
   <input type="hidden" name="r"      value="view.php?img=" />
// SETS THE ERROR PAGE, so if error is 2, will return fileupload.php?error=2 (you can see all error codes in http://php.net/manual/pt_BR/features.file-upload.errors.php)
   <input type="hidden" name="e"      value="fileupload.php?error=" />
   <input type="file"   name="file">
   <input type="submit" name="upload" value="Upload">
</form>

uploadfile.php

<?php
if(isset($_POST['upload'])){
  echo "<h1><font face='Arial'><b>Wait. . .</font></h1>";
  $filname    = $_POST['nam'] . strrchr($_FILES['file']['name'], '.');
  $uploaddir  = '$_POST['f'] . '/' . $filname;

  if(move_uploaded_file($_FILES['file']['tmp_name'], $uploaddir)){
    echo "<script> location.href='" . $_POST['r'] . $filname . "'; </script>";
  } else {
    echo "<script> location.href='" . $_POST['e'] . $_FILES['file']['error'] . "'; </script>";

  }
}
 ?>

小心: 它没有100%的安全性,如果其他人使用此代码创建 uploader.php ,他可以上传太

希望有所帮助

答案 3 :(得分:0)

你可以google,有很多关于如何使用curl的教程。在您的情况下,您需要在两台服务器上开发两个部分:

  1. 接收表格,等待上传文件(收件人)
  2. 卷曲上传脚本(发件人)
  3. 发件人脚本可能相似:

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, array('file' => '@/path/to/file.txt'));
    curl_setopt($ch, CURLOPT_URL, 'http://yoursecondserver.com/upload.php');
    curl_exec($ch);
    curl_close($ch);
    

    如何在PHP手册中阅读的第二台服务器上接收文件,大量示例http://php.net/manual/en/features.file-upload.php

    您可能希望使用 FTP连接,如果在服务器上安装了它,则可能更容易。

答案 4 :(得分:0)

首先,确保其他服务器接受您的连接,查找跨域策略问题。此外,请确保该文件是公开可用的(即:您可以通过使用标准浏览器导航到URL下载它)。

设置完所有内容后,您可以使用file_get_contents获取文件内容,并使用file_put_contents将其保存在本地:

.controller('DistinctSupplierCtrl', function($scope, $http) { $scope.selectAction = function() { console.log($scope.Supplier); }; var xhr = $http({ method: 'post', url: 'http://localhost/api/list-distinct-supp.php' }); xhr.success(function(data){ $scope.data = data.data; }); }) .controller('MatIncListCtrl', function ($scope, $http) { $scope.FindMatInc = function (){ console.log($scope.Supplier); } });

您的其他问题(删除,编辑)实际上是一个不同的野兽,应该最有可能在他们自己的问题中处理,因为出于明显的安全原因,无法单独从您的网站服务器执行此操作。 您需要在存储服务器上公开API并从网站点击该API以使存储执行适当的操作。

答案 5 :(得分:0)

您可以使用发布文件在其他服务器上上传文件。

$request = curl_init('http://example.com/');

// send a file
curl_setopt($request, CURLOPT_POST, true);
curl_setopt(
    $request,
    CURLOPT_POSTFIELDS,
    array(
      'file' => '@' . realpath('example.txt')
    ));

curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($request);

curl_close($request);
  

您可以使用$ _FILES ['file']

处理上传的文件

答案 6 :(得分:0)

在这种情况下,您可以在远程服务器上调用PHP脚本,并提供本地服务器上文件的路径。 然后在使用file_get_contents的远程服务器上保存文件。 本地服务器上的示例:

<?php
file_get_contents('http://somestaticfilesserver.com/download.php?file=path/to/some/file.png')

和download.php可能如下所示:

<?php
$remoteHost = 'http://serversendingfile.com';
$rootPath = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'uploaded' . DIRECTORY_SEPARATOR;
$filePath = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, filter_input_array(INPUT_GET)['file']);
$fileName = (basename($filePath));
$remoteFile = $remoteHost . $filePath;
$file = file_get_contents($remoteFile);
$absolutePath = str_replace($fileName, '', $rootPath . $filePath);
if (!is_dir($absolutePath)) {
    mkdir($absolutePath, 0777, true);
}
if (file_put_contents($absolutePath . $fileName, $file, FILE_APPEND)) {
    die('ok');
}
die('nok');

给定路径将相对于$ rootPath

保留