0

GOAL: I am trying to attach local image files to a photoscene in python3.8 using the requests library.

PROBLEM: After attaching the files, and starting processing, I discover that Forge reports an error and that no model file is produced.

CODE: I believe the problem code is within this snippet which I perform for each image file I want to attach:

data = {'filename': file_name,
        'photosceneid': photoscene_id,
        'type': 'image'}
files = {'files': open(file_name,'rb')}

r = requests.post(url, data=data, headers=headers, files=files)
content = eval(r.content) 

Diagnostics: Although Forge is reporting "No Error" as the returned "Msg" field for each of these attachment calls, Forge also reports the FILE SIZE = 0 bytes. This is erroneous as the actual size of each file to attached is between 1-2 MB each.

I am guessing that it is not actually reading the file contents defined in the files= argument, and that is why it is probably reporting zero length.

I am confused about where and how to specify the local files among the data=, files= and headers= arguments passed to requests.post(). Can someone show me a correct code example in python?

Larger code snippet (for context if needed):

list_of_JPGs  = {
    'LRC21738.jpg', 'LRC21728.jpg', 'LRC21729.jpg',
    'LRC21730.jpg', 'LRC21725.jpg', 'LRC21731.jpg',
    'LRC21727.jpg', 'LRC21733.jpg', 'LRC21732.jpg', 
    'LRC21726.jpg', 'LRC21736.jpg', 'LRC21737.jpg', 
    'LRC21735.jpg', 'LRC21734.jpg'}  

access_token = get_access_token()    # attach JPGs to Autodesk Forge 
photoscene_id = get_new_photoscene()

url = 'https://developer.api.autodesk.com/photo-to-3d/v1/file'
headers = {'Authorization': 'Bearer ' + access_token}

i = 0
print('FILE #\tFILE NAME\tSIZE\tMSG')
for file_name in list_of_JPGS:

    data = {'filename': file_name,
            'photosceneid': photoscene_id,
            'type': 'image'
        }
    files = {'files': open(file_name,'rb')}

    r = requests.post(url,  data=data, headers=headers, files=files)
    content = eval(r.content)

    try:
        photoscene_id = content['photosceneid']
        files_items = content['Files']
        file_tupple = files_items['file']
        filename = file_tupple['filename']
        filesize = file_tupple['filesize']
        msg = file_tupple['msg']
        print (f'file[{i}]: {filename}\t{filesize}\t{msg}')

    except:
        print(f'WARNING: attaching {file_name} to photoscene {photoscene_id} failed.')
        try:
            request_error = content['Error']
            errormsg = request_error['msg']
            print(errormsg)
            errorcode = request_error['code']
            print(errorcode)
        except:
            print(f"ERROR 8: Request to attach {file_name} to photoscene {photoscene_id} failed without a message.")
            sys.exit(8)
    i = i + 1
    print(f"{i} images were attached to {photoscene_id}.\n Ready to Begin Modeling")

Output from code above:

FILE #    FILE NAME    SIZE MSG
file[0]:  LRC21738.jpg  0   No error
file[1]:  LRC21728.jpg  0   No error
file[2]:  LRC21729.jpg  0   No error
file[3]:  LRC21730.jpg  0   No error
file[4]:  LRC21725.jpg  0   No error
file[5]:  LRC21731.jpg  0   No error
file[6]:  LRC21727.jpg  0   No error
file[7]:  LRC21733.jpg  0   No error
file[8]:  LRC21732.jpg  0   No error
file[9]:  LRC21726.jpg  0   No error
file[10]: LRC21736.jpg  0   No error
file[11]: LRC21737.jpg  0   No error
file[12]: LRC21735.jpg  0   No error
file[13]: LRC21734.jpg  0   No error
14 images were attached to O9ukPcj2u47iV43WqOzrvwCLQ5NN8E75NrA64DPU2SA. 
Ready to Begin Modeling
     

Evidence that attachments failed

After attaching all the image files I used

f'https://developer.api.autodesk.com/photo-to-3d/v1/photoscene/{photoscene_id}'

as my url to commence modeling, and then I used

f'https://developer.api.autodesk.com/photo-to-3d/v1/photoscene/{photoscene_id}/progress'

to poll for progress.

After 140 seconds, Forge began processing, but then quickly exited with an ERROR as its progress message value:

TIME:   PROGRESSMSG PROGRESS
147s:   Processing  10%
158s:   ERROR       100%

As you might expect after receiving this error message, attempts to retrieve a model (OBJ file) using:

f'https://developer.api.autodesk.com/photo-to-3d/v1/photoscene/{photoscene_id}?format=obj'

also fail, as you can't retrieve a model if none was produced.

mcgregor94086
  • 1,467
  • 3
  • 11
  • 22

1 Answers1

2

Additional reading and experimentation confirmed that incorrect coding of the data= and files= arguments were the source of the error.

The source of the problem is that the files themselves need to be identified as mime type "images/jpg", but the other data= Form information, such as the PhotosceneID, are text.

Resolving that conflict required creating a Multipart-encoded payload in the data= argument and eliminatinguse of the file= argument.

The following is my changed code using MultipartEncoder to work around the problem and this code seems to be working for me now:

Code that worked for me:

url = 'https://developer.api.autodesk.com/photo-to-3d/v1/file'

payload = MultipartEncoder(
    fields={'photosceneid': photoscene_id,
            'type': 'image',
            'file[0]': (file_name, open(file_name, 'rb'), 'image/jpg')
            }
)

headers = {'Content-Type': payload.content_type,
           'Authorization': 'Bearer ' + access_token}

r = requests.post(url, headers=headers, data=payload)
content = eval(r.content)

Note: I think a better answer is still needed. The discussion at: https://stackoverflow.com/a/52396494/2708519 seems to suggest that this method for multipart encoding is no longer necessary, and that use of the proper files= arguments avoids the need for that.

However,I have not got the files= approach to work for me yet. So even though I think it is probably the better solution for the future, I am sharing the workaround solution that is working for me. I hope others will share a more up to date version.

mcgregor94086
  • 1,467
  • 3
  • 11
  • 22