tfatool icon indicating copy to clipboard operation
tfatool copied to clipboard

Delete files on FlashAir

Open hntuan94 opened this issue 6 years ago • 20 comments

Hi,

Can I delete the files on FlashAir?

hntuan94 avatar Sep 10 '18 03:09 hntuan94

Hey @hntuan94, try out the branch in pull request #9 for the ability to delete from the command line. It hasn't been merged because it's not fully tested, so if you can test it with a FlashAir device we can merge it!

TadLeonard avatar Sep 10 '18 07:09 TadLeonard

Hi @TadLeonard ,

  • Before testing the delete function I already tried using CGI on the web browser and got the following error: Command: http://flashair/upload.cgi?DEL=/DCIM/100__TSB/EK000003.JPG Response: 500 Server Error The server encountered an internal error and could not complete your request.

  • Reference: https://flashair-developers.com/en/documents/api/uploadcgi/

  • I don't know if the new firmware does not allow to delete remotely. Any idea?

hntuan94 avatar Sep 11 '18 04:09 hntuan94

Hi @TadLeonard ,

Simple modification I could delete file using CGI. I'll test the delete function and let you know soon. In the /SD_WLAN/ folder open the CONFIG file with notepad or a text editor and add 'UPLOAD=1' into config file. https://shop.prusa3d.com/forum/user-mods-octoprint-enclosures-nozzles--f65/flashair-wifi-sd-card-setup-and-drive-mapping-t13693.html

hntuan94 avatar Sep 11 '18 05:09 hntuan94

Hey @hntuan94, yeah that UPLOAD=1 thing is an annoying feature. I suppose it's for security, but the device is not secure to begin with.

TadLeonard avatar Sep 11 '18 05:09 TadLeonard

Hi @TadLeonard ,

I found an issue with delete function.

def delete_file(remote_file: str, url=URL):
    response = get(url=url, **{Upload.delete: remote_file})
    if response.status_code != 200:
        raise UploadError("Failed to delete file", response)
    return response

It seems that you have not added the DEFAULT_REMOTE_DIR. So when I run the test the request output is shown below: http://flashair/upload.cgi?DEL=EK000001.JPG If I add the DEFAULT_REMOTE_DIR It will work well. upload.delete_file("=/DCIM/100__TSB/EK000006.JPG")

hntuan94 avatar Sep 12 '18 05:09 hntuan94

Hey @hntuan94,

That's a good idea. Another way to solve this would be to use the branch in pull request #13. The branch solves these problems by having all functions take a Session, which contains this info:

class _Session(NamedTuple):
    url: str = URL  # device URL (http://flashair by default)
    remote_dir: str = DEFAULT_REMOTE_DIR  # /DCIM/100__TSB by default
    local_dir: str = "."  # local directory for sychronizing files
    filters: Tuple[Callable] = ()

This means that we could rewrite the delete_file function to join Session.remote_dir with the remote_file argument.

The reason I haven't merged #13 is because I can't test it. If you are able to make the changes you need to delete_file and test them, it'd be great to merge this and cut a new release.

Regards, Tad

TadLeonard avatar Sep 12 '18 06:09 TadLeonard

To be clear, the way we might solve it is to make (and test) this adjustment in the session branch:

Take this function as it is currently defined:

def delete_file(remote_file: str, session: Session = Session()):
    response = get(url=url, **{Upload.delete: remote_file)
    if response.status_code != 200:
        raise UploadError("Failed to delete file", response)
    return response

...and make some small changes like this:

import pathlib  # near the top of the file

...

def delete_file(remote_file: str, session: Session = Session()):
    remote_file = pathlib.PurePosixPath(session.remote_dir, remote_file)
    response = get(url=url, **{Upload.delete: str(remote_file))
    if response.status_code != 200:
        raise UploadError("Failed to delete file", response)
    return response

TadLeonard avatar Sep 12 '18 06:09 TadLeonard

That's great. I modified your function a little and it works.

def delete_file(remote_file: str, session: Session = Session()):
    remote_file = pathlib.PurePosixPath(session.remote_dir, remote_file)
    response = get(url=session.url, **{Upload.delete: str(remote_file)})
    if response.status_code != 200:
        raise UploadError("Failed to delete file", response)
    return response

The response's [200] even thought I delete an unavailable file. Any idea? <Response[200]>

I tried the CGI if there's no file the response will be NG

hntuan94 avatar Sep 12 '18 07:09 hntuan94

The response's [200] even thought I delete an unavailable file. Any idea? <Response[200]>

I tried the CGI if there's no file the response will be NG

Hmm, this is very strange. Do you get any useful log messages when this happens? Maybe we can compare the full CGI URL used against the URL you tested manually.

TadLeonard avatar Sep 12 '18 07:09 TadLeonard

In order to raise the error. May we use response.text instead of response.status_code How you do think of?

Ref: https://stackoverflow.com/questions/40488882/pythons-request-get-only-show-200-status

hntuan94 avatar Sep 12 '18 07:09 hntuan94

The response of CGI is below: SUCCESS NG

hntuan94 avatar Sep 12 '18 07:09 hntuan94

In order to raise the error. May we use response.status_code instead of response.status_code How you do think of?

Oh, do you mean that we should use the text instead of the status code? I think that makes sense. From the docs it seems we could make the check be this:

if response.text != "SUCCESS":
    raise UploadError(...)

TadLeonard avatar Sep 12 '18 07:09 TadLeonard

Actually even better would be this:

if response.text != info.ResponseCode.success:
    raise ...

TadLeonard avatar Sep 12 '18 07:09 TadLeonard

Yeah! I did it :)

hntuan94 avatar Sep 12 '18 07:09 hntuan94

Great! Please feel free to make a PR with those changes. I can then merge it into session. Also, if you can run the functional tests with your FlashAir device connected (and if they pass) I'll make a new release and tfatool will be much better off!

TadLeonard avatar Sep 12 '18 07:09 TadLeonard

Hi @TadLeonard ,

We can use delete function from now on. Do we need to support deleting folder? or close the issue?

Many thanks for your support.

hntuan94 avatar Sep 12 '18 07:09 hntuan94

Do we need to support deleting folder? or close the issue?

I think it's probably best to leave that up to the user (for now). It seems like folders are tricky on FlashAir. You may have read this in their docs already, but if you attempt deleting a folder without deleting the files inside it first you'll never be able to recover the files again! They'll just sit around taking up space, yet they'll be unreadable and undeletable. Scary.

TadLeonard avatar Sep 12 '18 07:09 TadLeonard

I ordered another FlashAir device a few hours ago, so in a week I'll finally be able to test on my own. Then I can make a new release and you'll be able to pip install the changes you've suggested.

If you want a release earlier, you can help out by running the functional tests and pushing a few PRs. Otherwise we'll get these improvements released to pip eventually anyway.

Thank you very much for your help in identifying these problems, @hntuan94!

TadLeonard avatar Sep 12 '18 07:09 TadLeonard

I ordered another FlashAir device a few hours ago, so in a week I'll finally be able to test on my own. Then I can make a new release and you'll be able to pip install the changes you've suggested.

If you want a release earlier, you can help out by running the functional tests and pushing a few PRs. Otherwise we'll get these improvements released to pip eventually anyway.

Thank you very much for your help in identifying these problems, @hntuan94!

I'm waiting for your new one. Once again, thank you very much for your contribution.

hntuan94 avatar Sep 12 '18 07:09 hntuan94

Why not using:

if response.code != info.ResponseCode:

I always recommend to compare numbers in these cases instead of strings :raising_hand: However, that might be my own style of coding :wink:

thopiekar avatar Sep 21 '18 23:09 thopiekar