Class: NVX::SDS::HttpUpload

Inherits:
Object
  • Object
show all
Defined in:
lib/nvx/sds/httpupload.rb

Overview

Overview

The HttpUpload is used to upload files via HTTP POST. This class can upload a maximum of 256gb.

Class Method Summary collapse

Class Method Details

.post_data(node, path, filename, file_data, offset, file_size, is_secure) ⇒ Object

A method to execute a nirvanix command with the parameters passed via a POST HTTP call.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/nvx/sds/httpupload.rb', line 80

def HttpUpload.post_data(node, path, filename, file_data, offset, file_size, is_secure)
    
    # setup headers including content-range to tell the upload what chunk we are uploading.
    boundary = "XYZBOUNDARY23487844XYZBOUNDARY1234567889"

    # setup the HTTP post data.
    content = "--" + boundary + "\r\n" +
    "Content-Disposition: form-data; name=\"File1\"; filename=\"#{filename}\"\r\n" +
    "Content-Transfer-Encoding: binary\r\n" +
    "Content-Type: application/octet-stream\r\n" +
    "Content-Range: #{offset}-#{offset + file_data.length - 1}/#{file_size}\r\n" +
    "\r\n" +                 
    "#{file_data}\r\n" + 
    "--" + boundary + "--\r\n"
    
    # pass headers including Content-Range to define the chunk that is being sent.
    headers = {
      'Content-Type' => "multipart/form-data; boundary=#{boundary}",
      'User-Agent' => USERAGENT
    }

    # set the port based on the is_secure flag.
    port = is_secure ? 443 : 80
    
    # Create the first http(s) object.
    h = Net::HTTP.new(node, port).start
    
    # if you are just testing and do not have a SSL certificate setup properly you can
    # disable warnings with the below line.  Just uncomment to ignore SSL session warnings.
    h.verify_mode = OpenSSL::SSL::VERIFY_NONE if is_secure
    
    # put the SSL in the correct mode based on the apicommand
    h.use_ssl = is_secure
    
    # do the upload and return the response.
    req = Net::HTTP::Post.new(path, headers)
    req.content_length = content.length
    req.content_type = "multipart/form-data; boundary=#{boundary}"
    req.body = content
    response = h.request(req)
    
    #print "\r\nContent: " + content + "\r\n\r\n"
    #print "RESPONSE XML: " +  response.body + "\r\n\r\n"

    # read the xml document and get any errors that are returned.
    doc = REXML::Document.new(response.body)
    response_code = (text = doc.root.elements["//Response/ResponseCode"].get_text and text.value)

    if response_code.to_i == 70121
      raise RetryException.new
    end
    if response_code.to_i != 0
        error_message = (text = doc.root.elements["//Response/ErrorMessage"].get_text and text.value)
        raise error_message
    end
    return doc
end

.UploadFile(destination_path, destination_filename, local_path, overwrite, account_login) ⇒ Object

Uploads a file to a destination and allows you to call overwrite.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/nvx/sds/httpupload.rb', line 31

def HttpUpload.UploadFile(destination_path, destination_filename, local_path, overwrite, )
    # Get the Upload node passing in the total file size.
    file_size = File.size(local_path)
    params = Array.new
    params << APIParam.new("sizeBytes", file_size)
    params << APIParam.new("destFolderPath", destination_path)
    params << APIParam.new("fileOverwrite", overwrite)
    
    result = Transport.execute_command_post(APICommand.GetStorageNodeExtended, params, )

    # extract the upload token, host name and build a new transfer object.
    upload_token = result.root.elements["//UploadToken"].get_text.value
    node = result.root.elements["//UploadHost"].get_text.value
    # set the URL based on the node that was returned from Nirvanix.

    # Open the local file
    file = File.open(local_path, "rb")
    offset = 0
    retry_count = 0
    path = "/upload.ashx?uploadToken=#{upload_token}&destFolderPath=#{destination_path}"
    # Loop through the entire file uploading each file part.
    while !file.eof?
        # read a chunk of data from the file.
        file_data = file.read(BLOCKSIZE)
        # Send a chunk to Nirvanix using the upload token and node.
        retry_chunk = false
        begin
          tmppath = path
          if retry_count > 0
            tmppath = path + "&rangeOverwrite=true"
          end
          params = post_data(node, tmppath, destination_filename, file_data, offset, file_size, false)
        rescue RetryException
          file.pos = offset
          retry_count += 1
          retry_chunk = true
          if retry_count == 10
            raise RetryException
          end
        end
        # advance offset based on how much data was read.
        if !retry_chunk
          offset += file_data.length
          retry_count = 0
        end
    end
end