2013-08-13 2 views
0

웹 사이트에 파일 업로드 양식이 있으며 사용자가 해당 파일을 내 서버에 업로드하면이 업로드 된 파일을 내 서버에서 클라우드 서버로 전송하려고합니다. 파일 크기가 클 수 있으므로 100KB 부분으로 클라우드로 파일을 전송하기로 결정했습니다. - 각 부분은 이전의 내용을 덮어PHP HTTP 1.1에서 부분 PUT 요청을 수행 할 수 없습니다.

<?php 
$cloud_server = '%my_server%'; 
$uploading_file_name = '%folders%/file.mp3'; 
$auth_token = '%token%'; 

$file_path = $_SERVER["DOCUMENT_ROOT"] . '/file.mp3'; 
$file_handler = fopen($file_path, 'rb'); 
$file_size = filesize($file_path); 
$chunk_size = 100 * 1024; 

$start_byte_position = 0; 

while (!feof($file_handler)) { 
    $chunk_content = fread($file_handler, $chunk_size); 
    $chunk_content_length = strlen($chunk_content); 
    $final_byte_position = $start_byte_position + $chunk_content_length; 

    $socket_handler = fsockopen($cloud_server, 80, $errno, $errstr); 
    if (!$socket_handler) 
     die ($errstr); 

    //Headers 
    $request = "PUT /{$uploading_file_name} HTTP/1.1\r\n"; 
    $request .= "Connection: Close\r\n"; 
    $request .= "Host: {$cloud_server}\r\n"; 
    $request .= "X-Auth-Token: {$auth_token}\r\n"; 
    $request .= "Content-Range: {$start_byte_position}-{$final_byte_position}/{$file_size}\r\n"; 
    $request .= "Content-Length: {$chunk_content_length}\r\n"; 
    $request .= "\r\n"; 

    //Body 
    $request .= $chunk_content; 
    $request .= "\r\n"; 

    fwrite($socket_handler, $request); 

    $server_response = ''; 
    while (!feof($socket_handler)) 
     $server_response .= fgets($socket_handler, 128); 
    echo $server_response, '<br><br>'; 

    $start_byte_position = $final_byte_position; 
    fclose($socket_handler); 
} 

그 코드는 실제로 한 가지를 제외하고 작동합니다

다음은 클라우드 내 서버에서 파일을 보내려고 내 PHP 코드 샘플입니다. 첫 번째 루프의 반복에서 100KB 파일이 클라우드에서 생성되고 두 번째 반복에서는 100KB가 다른 100KB로 대체됩니다. 마지막 반복에서 약 28KB가 업로드되므로 결국 전체 파일 대신 클라우드 서버에 28KB 파일이 생깁니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까? 나는이 부분들이 서로를 따라가는 것이지 교체하지 않기를 바란다.

HTTP/1.1 201 만든 날짜 : 여기

가 도움이 될 경우 서버 응답입니다 2013년 8월 13일 (화) 그리니치 표준시 15시 11분 9초 연결 : 가까운 서버 : Selectel_Storage/1.0 최종 수정 : Tue, 13 Aug 2013 15:11:09 GMT content-length : 0 etag : ea64231f21c952cdb57a5d3109415d09 content-type : text/html; 문자셋 = UTF-8

HTTP/1.1 201 만든 날짜 : 2013년 (화) 8월 13일 그리니치 표준시 15시 11분 10초 연결 : 가까운 서버 : Selectel_Storage/1.0 최종 수정 : 2013년 8월 13일 (화) 15:11 : 09 GMT content-length : 0 etag : 01ab42f6ad58b401284540d6631dae9d content-type : text/html; 문자셋 = UTF-8

HTTP/1.1 201 만든 날짜 : 2013년 (화) 8월 13일 그리니치 표준시 15시 11분 10초 연결 : 가까운 서버 : Selectel_Storage/1.0 최종 수정 : 2013년 8월 13일 (화) 15:11 : 10 GMT content-length : 0 etag : 99bd6f0d3cefd75abc140b9359464d6d content-type : text/html; 문자셋 = UTF-8

HTTP/1.1 201 만든 날짜 : 2013년 (화) 8월 13일 그리니치 표준시 15시 11분 10초 연결 : 가까운 서버 : Selectel_Storage/1.0 최종 수정 : 2013년 8월 13일 (화) 15:11 : 10 GMT content-length : 0 etag : 07cf64ef10e96710b8cb48022ee5dd16 content-type : text/html; 문자셋이 = UTF-8 등재

................................

HTTP/1.1 201 날짜 : 화요일, 13 8 월 2013 15:11:33 GMT 연결 : 닫기 서버 : Selectel_Storage/1.0 최종 수정 날짜 : 2012 년 8 월 13 일 화요일 15:11:33 GMT content-length : 0 etag : f01e66c96b21665bbb19ee5e283a4e1 content-type : text/html; charset = UTF-8

미리 감사드립니다.

+0

불가능합니다. http://stackoverflow.com/questions/2364110/whats-the-justification-behind-disallowing-partial-put –

+0

을 참조하십시오. 알겠습니다.하지만 여기에서 두 번째 대답에 대해 말할 수 있습니까? http://stackoverflow.com/questions/716680/difference-between-content-range-and-range-headers 내가 올바르게 이해한다면, 이것이 내가 원하는 것입니다. –

+0

서버에서 바이트 범위를 요청할 수 있습니다. content-range는 요청에 대한 응답으로 서버가 실제로 사용자에게 제공하는 것입니다 (요청한 것보다 적게 보낼 것을 결정할 수 있음). 이러한 특정 헤더가 존재한다고해서 PUT 요청에 부딪혀 부분적인 put을 시작한다는 것을 의미하지는 않습니다. 내가 링크 된 대답의 이유를 정확하게 말하십시오. 헤더는 서버에서 데이터를 요청하는 것이지 서버로 데이터를 보내지는 않습니다. –

답변

1

음, 마침내 적절한 해결책을 찾았습니다. Marc B이 응답 했으므로 부분 PUT 요청을 수행하는 것은 불가능합니다 (이 유형의 요청은 정의에 따라 멱등환이어야하므로). 그러나 거대한 클라우드 서버로 파일을 업로드하는 것에 대해 말하면 적절한 서버의 API를 사용할 수 있습니다. 내가 판단 할 수있는 한, OpenStack (정확한 Swift 구성 요소)은 파일 저장소 사이에서 충분히 인기가 있습니다.

따라서 here은 간단하고 명확한 공식 문서입니다.내가 사용하는

클라우드 서버 만 DLO로 큰 파일을 업로드 할 수 있습니다 (동적 대형 오브젝트) 방법은, 그래서 당신이 필요로하는 모든입니다

1) 세그먼트로 큰 파일을 분할 (또는 단순히 fseek과 및 FREAD를 사용).

2)이 세그먼트를 하나의 지정된 디렉토리로 보내십시오.이 이름은 전체 파일 이름으로 간주됩니다.

3) 다운로드 한 모든 세그먼트를 하나의 파일에 포함시켜 특수 요청 (소위 명시 파일 만들기)을 전송합니다.

아주 쉽습니다! 이 사람을 도움이 될

# First, upload the segments 
curl -X PUT -H 'X-Auth-Token: <token>' \ 
    http://<storage_url>/container/myobject/1 --data-binary '1' 
curl -X PUT -H 'X-Auth-Token: <token>' \ 
    http://<storage_url>/container/myobject/2 --data-binary '2' 
curl -X PUT -H 'X-Auth-Token: <token>' \ 
    http://<storage_url>/container/myobject/3 --data-binary '3' 

# Next, create the manifest file 
curl -X PUT -H 'X-Auth-Token: <token>' \ 
    -H 'X-Object-Manifest: container/myobject/' \ 
    http://<storage_url>/container/myobject --data-binary '' 

# And now we can download the segments as a single object 
curl -H 'X-Auth-Token: <token>' \ 
    http://<storage_url>/container/myobject 

희망 :

여기 CURL를 사용 the documentation page에서 좋은 예이다.

관련 문제