Reputation: 911
i am working on file upload into box.com but i am stuck there. i used Net::HTTP for that and i need the help of regarding this library.
my main code which interact to box.com is
module BoxApi
class FileOperation < Base
attr_reader :upload_path
def initialize
super
@upload_path = "https://upload.box.com/api/2.0/files/content"
end
#here filder_id args denote folder inside upload file and file args hold the content of file which are uploaded by file_field
def upload(folder_id, file)
boundary = "AaB03x"
body = []
body << "--#{boundary}\r\n"
body << "Content-Disposition: form-data; name='filename'; filename=#{file.original_filename}\r\n"
body << "Content-Type: text/plain\r\n\r\n"
body << file
body << "--#{boundary}\r\n"
body << "Content-Disposition: form-data; name='parent_id'"
body << "\r\n"
body << folder_id
body << "\r\n--#{boundary}--\r\n"
https_post(URI.parse("#{upload_path}"), body, boundary)
# `curl "Authorization: Bearer MlaNbyAefUWrawZEqGkDKvq9foCmQ0lL" -F filename=@./public/404.html -F parent_id='#{folder_id}' #{upload_path}`
rescue => ex
p "Exception caught (1) ==> #{ex}"
end
private
def https_post(uri, body, boundary)
http = https_setting(uri)
request = Net::HTTP::Post.new(uri.request_uri)
# request.body = JSON.parse(body)
request.body = body.join
request["Content-Type"] = "multipart/form-data, boundary=#{boundary}"
request["Authorization"] = "Bearer #{box_token.token}"
http.request(request)
rescue => ex
p "Exception caught (2) ==> #{ex}"
end
def https_setting(uri)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http
end
end
end
Upvotes: 2
Views: 801
Reputation: 3
Another translation of @NitrusCS into Python3 using the requests library. I was inspired by the bash code of @Kubuntuer82.
I'll include the gist here:
import datetime
import requests
import urllib
import os.path
import sys
import json
#
# Given a "File Request URL" and a local file, this program uploads to a box folder.
#
class BoxUploader(object) :
def __init__(self, requestURL) :
self.request_url = requestURL
o = urllib.parse.urlparse(requestURL)
self.boxDomain = o.hostname
self.fileRequestId = os.path.basename(o.path)
self.initialUrl = 'https://' + self.boxDomain + '/app-api/file-request-web/public/file-request?urlId=' + self.fileRequestId
self.formResponseUrl = 'https://' + self.boxDomain + '/app-api/file-request-web/public/form-response'
self.optionsUrl = 'https://' + self.boxDomain + '/api/2.1/files/content'
def upload_file(self, fname) :
#
# Initial call to the "get" url
#
rfc3339_format='%Y-%m-%dT%H:%M:%S%z'
response = requests.get(self.initialUrl)
jsonResponse = response.json()
basename = os.path.basename(fname)
local_timezone= datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
modifiedTime = datetime.datetime.fromtimestamp(os.path.getmtime(fname), tz=local_timezone)
#
# Submit a form response to get an upload token
#
boxFileRequestId = jsonResponse['id']
boxFolderId = jsonResponse['folder']['id']
formVersionId = jsonResponse['form']['versionId']
fileLength = os.path.getsize(fname)
print("Form Version ID: " + formVersionId)
requestContent = { "fileRequestURL" : self.fileRequestId,
"formVersionId" : formVersionId,
"values" : {"element-0" : { "type":"files", "data":[ {"local_path":fname, "size":fileLength}] },
"folder" : {"type" : "folder", "id": boxFolderId}}}
uploadFormResponse = requests.post(self.formResponseUrl, json=requestContent)
uploadFormResponseJson = uploadFormResponse.json()
#
# Make a call to the options url to get the actual url to
# upload the file to.
#
uploadToken = uploadFormResponseJson['uploadToken']
headers = { "Authorization" : "Bearer " + uploadToken }
requestContent = { "name" : fname,
"parent": { "id" : boxFolderId },
"size": fileLength}
optionsResponse = requests.options(self.optionsUrl, headers=headers, json=requestContent)
optionsResponseJson = optionsResponse.json()
# Upload the file.
upload_url = optionsResponseJson['upload_url']
form_attributes = { 'name' : fname,
'parent': {"id": boxFolderId},
'content_modified_at' : modifiedTime.strftime(rfc3339_format) }
files={ 'attributes' : (None, json.dumps(form_attributes), 'application/json', {'Content-Disposition':'form-data'}),
'file' : (fname, open(fname, 'rb')) }
#upload_request = requests.Request('POST', upload_url, headers=headers, files=files).prepare()
#print(upload_request.headers)
#print(upload_request.body)
uploadResponse = requests.post(upload_url, headers=headers, files=files)
print(json.dumps(uploadResponse.json(), indent=2))
def main(requestUrl, file) :
uploader = BoxUploader(requestUrl)
uploader.upload_file(file)
if __name__ == '__main__' :
url = sys.argv[1]
file = sys.argv[2]
main(url, file)
Upvotes: 0
Reputation: 1567
This is a translation of the code by @NitrusCS into Bash. It took a while and it's not identical, but it works.
#!/bin/bash
#CONSTANTS
BoxDomain="yourenterprise.ent.box.com"
formVersionId="1576913797"
#FUNCTIONS
function getdate() {
date "+%A, %B %d, %Y %I:%M:%S %p" | sed 's/am$/AM/g' | sed 's/pm$/PM/g'
}
function datetimeinticks() {
printf '%x\n' $(echo $(($(($(date '+%s') - $(date -d "0001-01-01T00:00:00.0000000 +0200" '+%s'))) * 10000000 + $((10#$(date '+%N')/100)) )))
}
#ARGUMENTS
FileRequestID="$1"
FileToUpload="$2"
FileName=$(basename $FileToUpload)
FileLength=$(stat --printf="%s" "$FileToUpload")
#MAIN CODE
URL="https://$BoxDomain/app-api/file-request-web/public/file-request?urlId=$FileRequestID"
echo -n "[$FileName] Preparing for upload: 0%"
resultsRaw=$(curl -s -X GET "$URL")
echo "$resultsRaw" > ${FileName}_errors.log
echo -en "\r[$FileName] Preparing for upload: 33%"
boxFolderId=$(echo $resultsRaw | jq ".folder" | jq ".id")
ProcessStartDateTime=$(getdate)
requestContent="{\"fileRequestURL\": \"$FileRequestID\",\"formVersionId\": \"$formVersionId\",\"values\":{\"element-0\":{\"type\":\"files\",\"data\":[{\"local_path\":\"$FileName\",\"size\":$FileLength}]},\"folder\":{\"type\":\"folder\",\"id\":$boxFolderId}}}"
UploadFormResponse=$(curl -s "https://$BoxDomain/app-api/file-request-web/public/form-response" -X POST -H "content-type: application/json;charset=UTF-8" -d "$requestContent")
echo "$UploadFormResponse" >> ${FileName}_errors.log
echo -en "\r[$FileName] Preparing for upload: 67%"
uploadToken=$(echo $UploadFormResponse | jq ".uploadToken" | sed 's/^\"//g' | sed 's/\"$//g')
requestContent="{\"name\":\"$FileName\",\"parent\":{\"id\":$boxFolderId},\"size\":$FileLength}"
OptionsResponse=$(curl -s "https://$BoxDomain/api/2.1/files/content" -X OPTIONS -H "Authorization: Bearer $uploadToken" -d "$requestContent")
echo "$OptionsResponse" >> ${FileName}_errors.log
echo -e "\r[$FileName] Preparing for upload: 100% ... "
UploadURL=$(echo $OptionsResponse | jq ".upload_url" | sed 's/^\"//g' | sed 's/\"$//g')
boundary="---------------------------$(datetimeinticks)"
LastWriteTimeUtc=$(date -u -d "$(stat --printf=%y "$FileToUpload")" '+%Y-%m-%dT%H:%M:%SZ')
boundarystring="$(echo -en "\r\n--" ; echo -n $boundary ; echo -en "\r\n" ; echo .)"
boundarystring=${boundarystring%.}
rs="${FileName}_requestdata.http"
touch $rs
echo -n "$boundarystring" > $rs
formAttributes="$(echo -en "Content-Disposition: form-data; name=\"attributes\"\r\n\r\n{\"name\":\"$FileName\",\"parent\":{\"id\":$boxFolderId},\"content_modified_at\":\"$LastWriteTimeUtc\"}" ; echo .)"
formAttributes=${formAttributes%.}
echo -n "$formAttributes" >> $rs
echo -n "$boundarystring" >> $rs
formFile="$(echo -en "Content-Disposition: form-data; name=\"file\"; filename=\"$FileName\"\r\nContent-Type: application/octet-stream\r\n\r\n" ; echo .)"
formFile=${formFile%.}
echo -n "$formFile" >> $rs
echo -n "[$FileName] Preparing the file to upload..."
cat "$FileToUpload" >> $rs
trailerstring="$(echo -en "\r\n--" ; echo -n $boundary ; echo -en "--\r\n" ; echo .)"
trailerstring=${trailerstring%.}
echo -n "$trailerstring" >> $rs
echo "[$FileName] Uploading:"
response=$(curl -X POST -H "content-type: multipart/form-data; boundary=$boundary" -H "Authorization: Bearer $uploadToken" --data-binary @$rs "$UploadURL")
echo "$response" >> ${FileName}_errors.log
echo $response | grep -q '"type":"file"' && { echo "[$FileName] Upload complete" ; rm ${FileName}_errors.log ; rm $rs ; }
echo $response | grep -q '"type":"file"' || echo "[$FileName] Upload failed: See file ${FileName}_errors.log for details."
Upvotes: 0
Reputation: 753
Here's my Powershell code which uses System.Net.HttpWebRequest
param(
$FileRequestID ,
$FileToUpload
)
$BoxDomain = "yourenterprise.ent.box.com"
$URL = "https://$($BoxDomain)/app-api/file-request-web/public/file-request?urlId=$($FileRequestID)"
$resultsRaw = Invoke-WebRequest -Uri $URL -Method GET -UseBasicParsing
$resultsJson = ConvertFrom-Json $resultsRaw.Content
$boxFileRequestId = $resultsJson.id
$boxFolderId = $resultsJson.folder.id
$fileInfo = [System.IO.FileInfo]$FileToUpload
$ProcessStartDateTime = Get-Date
$ProgressName = "$($fileInfo.Name) Upload Progress"
$requestContent = "{`"fileRequestURL`":`"$($FileRequestID)`",`"formVersionId`":`"303881722`",`"values`":{`"element-0`":{`"type`":`"files`",`"data`":[{`"local_path`":`"$($fileInfo.Name)`",`"size`":$($fileInfo.Length)}]},`"folder`":{`"type`":`"folder`",`"id`":`"$($boxFolderId)`"}}}"
$UploadFormResponse = Invoke-WebRequest -Uri "https://$($BoxDomain)/app-api/file-request-web/public/form-response" -Method POST -ContentType "application/json;charset=UTF-8" -Body $requestContent -UseBasicParsing
$UploadFormResponseJson = ConvertFrom-Json $UploadFormResponse.Content
$requestContent = "{`"name`":`"$($fileInfo.Name)`",`"parent`":{`"id`":`"$($boxFolderId)`"},`"size`":$($fileInfo.Length)}"
$OptionsResponse = Invoke-WebRequest -Uri "https://$($BoxDomain)/api/2.1/files/content" -Method OPTIONS -Body $requestContent -Headers @{ Authorization = "Bearer $($UploadFormResponseJson.uploadToken)";} -UseBasicParsing
$OptionsResponseJson = ConvertFrom-Json $OptionsResponse.Content
$UploadURL = $OptionsResponseJson.upload_url
$boundary = "---------------------------" +[System.DateTime]::Now.Ticks.ToString("x");
$boundarybytes = [System.Text.Encoding]::ASCII.GetBytes("`r`n--" + $boundary + "`r`n");
$wr = [System.Net.HttpWebRequest]([System.Net.WebRequest]::Create($UploadURL));
$wr.ContentType = "multipart/form-data; boundary=" + $boundary;
$wr.Method = "POST";
$wr.KeepAlive = $true;
$wr.PreAuthenticate = $true
$wr.Headers.Add("Authorization", "Bearer $($UploadFormResponseJson.uploadToken)")
$wr.AllowWriteStreamBuffering = $false
$wr.SendChunked = $true
$rs = $wr.GetRequestStream();
#Write attributes
$rs.Write($boundarybytes, 0, $boundarybytes.Length);
$formAttributes = "Content-Disposition: form-data; name=`"attributes`"`r`n`r`n{`"name`":`"$($fileInfo.Name)`",`"parent`":{`"id`":`"$($boxFolderId)`"},`"content_modified_at`":`"$($fileInfo.LastWriteTimeUtc.ToString("yyyy-MM-ddTHH:mm:ssZ"))`"}"
$formAttributesBytes = [System.Text.Encoding]::UTF8.GetBytes($formAttributes)
$rs.Write($formAttributesBytes, 0, $formAttributesBytes.Length)
#Write File
$rs.Write($boundarybytes, 0, $boundarybytes.Length);
$formFile = "Content-Disposition: form-data; name=`"file`"; filename=`"$($fileInfo.Name)`"`r`nContent-Type: application/octet-stream`r`n`r`n"
$formFileBytes = [System.Text.Encoding]::UTF8.GetBytes($formFile)
$rs.Write($formFileBytes, 0, $formFileBytes.Length)
[System.IO.FileStream]$fileStream = [System.IO.File]::Open($fileInfo.FullName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$buffer = [System.Byte[]]::new(1048576)
$bytesRead = 0;
$totalBytesRead = 0
$totalBytesToRead = $fileInfo.Length
while (($bytesRead = $fileStream.Read($buffer, 0, $buffer.Length)) -ne 0) {
$rs.Write($buffer, 0, $bytesRead);
$rs.Flush()
$totalBytesRead += $bytesRead
$SecondsElapsed = ((Get-Date) - $ProcessStartDateTime).TotalSeconds
$SecondsRemaining = ($SecondsElapsed / ($totalBytesRead / $totalBytesToRead)) - $SecondsElapsed
Write-Progress -Activity $ProgressName -PercentComplete (($totalBytesRead/$($totalBytesToRead)) * 100) -CurrentOperation "$("{0:N2}" -f ((($totalBytesRead/$($totalBytesToRead)) * 100),2))% Complete" -SecondsRemaining $SecondsRemaining
}
$fileStream.Close();
$trailerBytes = [System.Text.Encoding]::ASCII.GetBytes("`r`n--" + $boundary + "`r`n");
$rs.Write($trailerBytes, 0, $trailerBytes.Length);
$rs.Close();
#Done writing File
$wresp = $wr.GetResponse();
$wresp.StatusCode
$stream2 = $wresp.GetResponseStream();
$reader2 = New-Object -TypeName System.IO.StreamReader -ArgumentList $stream2
$response = ConvertFrom-Json ($reader2.ReadToEnd())
#$response
Upvotes: 1