Need FTP the file without storing interpreter file save in local through Python

Question:

I am trying to do some image interpreter and trying to store them directly to FTP server.

But my steps like upload the image from local folder then it converts to mask image then it will have final output. But during my mask and final output scenarios, temporary images are getting save it local which I don’t want.

But without storing the image in local I unable to save the file to FTP. Please help me with solution that output.save(mask_img_path) without this step how can store the image in FTP.

import errno
from flask import Flask,request
from rembg import remove
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import time
import random
import ftplib
import os

app = Flask(__name__)

input_img_path = "C:/Projects/Python/input/1.jpg"
output_img_path = "C:/Projects/Python/image-processing-2/image/output/"

mask_img_path = output_img_path + 'mask.png'
mask_img = 'mask.png'

input_img = Image.open(input_img_path)
output = remove(input_img)
output.save(mask_img_path) // without this step unable to FTP the file below because this step storing the mask images in the folder.

ftp = ftplib.FTP('host', 'username', 'password')

# Store the mask files into FTP
with open(mask_img_path, "rb") as file:
    ftp.storbinary('STOR %s' % mask_img, file)

if __name__ == '__main__':
    app.run(debug=True,port=2000)

Given about all my coding step and strying to FTP the converted image.

Asked By: Manoj Poosalingam

||

Answers:

I presume your question is really *"How do I call ftplib.storbinary() without needing a disk file. The short answer is via io.BytesIO:

Here we make a PIL Image

from PIL import Image
from io import BytesIO

# Create dummy red PIL Image
output = Image.new('RGB', (320,240), 'red')

and save it in aBytesIO:

# Create in-memory JPEG
buffer = BytesIO()
output.save(buffer, format="JPEG")

Now you should be able to pass that to ftplib():

ftp.storbinary('STOR image.jpg', buffer)

You may need to do the following before FTPing:

buffer.seek(0)

I can’t test as I don’t have any FTP servers.

Answered By: Mark Setchell

You can use io.BytesIO whenever you need to keep a file object in memory instead of having to save it to a temporary file. (But if you have big files that would not be practical to keep them all in memory, have a look at the tempfile module of the standard library.

Let’s suppose that you have

  • an FTP server
    • running on localhost
    • at port 60000
    • accessible with the user name "Manoj"
    • and password "Poosalingam"
  • an image 1.jpg
    A dog on a wooden floor

Using this code:

import io
import ftplib
from PIL import Image
from rembg import remove

image_filename = "1.jpg"

with Image.open(image_filename) as input_image:
    with remove(input_image) as output:
        with io.BytesIO() as temporary_file:
            output.save(temporary_file, format='PNG')
            temporary_file.seek(0) # Rewinding to the start of the file

            with ftplib.FTP() as ftp_client:
                remote_filename = 'mask.png'
                ftp_client.connect(host='localhost', port=60000)
                ftp_client.login(user='Manoj', passwd='Poosalingam')
                ftp_client.storbinary(f'STOR {remote_filename}', temporary_file)

I get this mask.png image on the server:

A dog with the background all stripped

Is that what you needed?

Answered By: EvensF