Send .txt file from one pc to another using http service

3

I need to send a file from one PC to another over the network, only using link requests, so I do not have to download at the socket level, which gives a job. Is anyone able to clear me with some API or code sample?

PS: I'm not lazy, until I found some things, but I had to make a mini server and I'm kind of lazy about it. Oh, I'm using Java and / or Python.

    
asked by anonymous 31.01.2016 / 21:59

1 answer

2

Receiving an HTTP file as a web request, without using a framework, is not as trivial as this:

In order to guarantee the passage of the data of the file, along with other possible form data, and other things that go in an HTTP post, the thing is well chatinha.

I made a program in Python 3- without using a framework, just using the http.server module to receive a file - it works, but it "rips" the file data from inside the HTTP post without parsing correctly . Certainly there are dozens of corner-cases that are not treated (not that they are not treated right - they simply are not treated). In particular the post data is read as "bytes" and has no cool Python search methods available and cut strings. In particular I do a necessary trick: a transparent conversion of these bytes to string with the codec "latin1" - this preserves the numerical value of each byte, as a unicode character of equivalent value in the string - and in the string object, I can use split , find, slices, etc ...

On the other hand, I think there's a nice example of how to use the "http.server" of Python 3 (BaseHTTPServer module) in Python2.

# coding: utf-8
from http.server import HTTPServer, BaseHTTPRequestHandler
import cgi

UPLOAD_DIR = "/tmp/"

class FileSaver(BaseHTTPRequestHandler):
    def _headers(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html;charset=utf-8")
        self.end_headers()

    def do_POST(self):
        files = []
        try: 
            raw_file_content = self.rfile.read(int( self.headers.get('content-length')))
            data = raw_file_content.decode("latin1")
            while True:
                try:
                    header, data = data.split("\r\n\r\n", 1)
                except ValueError:
                    break
                boundary_str = header.split("\r\n", 1)[0]
                if "filename" in header:
                    file_data = data.split("\r\n" + boundary_str)[0].encode("latin1")
                    filename = header.split('filename="')[1].split('"')[0]

                    with open(UPLOAD_DIR + filename, "wb") as file_:
                        file_.write(file_data)
                    files.append(filename)
                data = data[data.find(boundary_str):]
                if len(data) < 2:
                    break
        except Exception as exc:
            self.send_response(500)
            self.send_header("Content-type", "text/plain;charset=utf-8")
            self.end_headers()
            self.wfile.write(str(exc).encode("utf-8"))
            raise
        self._headers()
        self.wfile.write("""<h1 style="color:red">upload of {} ok</h1>""".format(filename).encode("utf-8"))
        return

    def do_GET(self):
        self._headers()

        self.wfile.write("""<h1 style="color:red">Alô mundo!!</h1>
            <form method="post" action="/" enctype="multipart/form-data">
            arquivo: <input type="file" name="arquivo"><br/>
            <input type="submit" value="ok" / >
            </form>

            """.encode("utf-8"))
        return


if __name__ == "__main__":
    server = HTTPServer(("0.0.0.0", 8000), FileSaver)
    server.serve_forever()

Of course using a framework like Flask, it is well easier to do this. A view that saves a file that has been in a Flask forum, using the WTF forms extension (with the framework already taking care of all the above) would be something like:

from flask import Flask, render_template
import flask_wtf

app = Flask(__name__)

class FileForm(form):
     file = flask_wtf.file.FileField

@route("/upload", methods=["POST"])
def upload(form, id):
    form.file.data.save("/tmp/" + form.file.data.filename)
    return render_template(...)

(This code in Flask is not complete and has not been tested - the one in Python raw works the way it is)

Now the code to post a file via HTTP - again, if using "raw" Python can be very complicated - but in this case, we can use the "requests" method that accepts a "file" parameter directly (it receives a dictionary with the name of the file field and an open file, which we wish to send):

>>> requests.post("http://localhost:8000", files={"arquivo": open("imagem.png", "rb")  } )

Only this call uploads the file to the first server in Listing 1 above.

Now, it's one thing to want to play with it, another is to want to use it in production - in that case it's better to use the framework, of course, or use xmlrpc (or jsonrpc) - it's going to be an order of magnitude easier. p>     

03.02.2016 / 16:37