【问题标题】:Form uploading files to different server without following表单将文件上传到不同的服务器而不跟随
【发布时间】:2011-04-28 05:18:36
【问题描述】:

如何在不将用户重定向到服务器的情况下将 django 中的文件发送到不同的服务器?所以一切都在 django 中重写这个简单的 php 函数:

$filename = 'C:/tmp/myphoto.jpg';
$handler  = 'http://www.example.com/upload.php';
$field    = 'image';
$res = send_file($filename, $handler, $field);

if ($res) {
    echo 'done.';
} else {
    echo 'something went wrong.';
}

第二台服务器上的函数只是从$_FILES读取文件的简单php func:

<?php
    move_uploaded_file(
        $_FILES['image']['tmp_name'],
        '/var/www/image/uploaded-file.jpg'
    );
    echo 'file saved.';
?>

我已经尝试过django-filetransfers,它可以工作,但我无法让它停留在我上传文件的页面上。我已经编辑了 upload_handler 视图并且文件已正确发送,但之后我被重定向到我的第二台服务器:

def upload_handler(request):
    if request.method == 'POST':
        form = UploadForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
        return HttpResponseRedirect("/upload")

    upload_url, upload_data = prepare_upload(request, "address of my server/")
    form = UploadForm()
    return direct_to_template(request, '/upload.html',
        {'form': form, 'upload_url': upload_url, 'upload_data': upload_data,
         'uploads': UploadModel.objects.all()})

这是我的方法。我正在使用来自 httplib 的函数以及来自 python-poster 的 multipart_encode 函数,它创建了我的文件头:

def file_upload(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            f = request.FILES['file']
            logging.debug(f)
            status = send_file(request.FILES['file'])
            c = RequestContext(request, {
                "status" : status,
            })
            template = "management/status.html"
            result = render_to_string(template, c)
            return HttpResponse(result)
    else:
        form = UploadFileForm()
    return render_to_response('management/file_upload.html', {'form': form})


def send_file(file):
    datagen, headers = multipart_encode({"myfile": file})
    conn = httplib.HTTPConnection(HOST)
    conn.request('POST', '/rte/', file, headers)
    res = conn.getresponse()

    if res.status != 200:
        logging.debug("error \n")
        logging.debug(file)
        logging.debug("\n")
        logging.debug(headers)
    return res.status

HTML:

<form action="{{ views.file_upload }}" method="POST" enctype="multipart/form-data">
    {{ form.as_p }}
  <input type="submit" value="Upload" />
</form>

结果我得到“错误 500”并在调试中:

2010-10-20 18:12:55,819 DEBUG thumb.php4.jpg
2010-10-20 18:14:55,968 DEBUG error 
2010-10-20 18:14:55,968 DEBUG thumb.php4.jpg
2010-10-20 18:14:55,969 DEBUG 
2010-10-20 18:14:55,969 DEBUG {'Content-Length': 15019, 'Content-Type': 'multipart/form-data; boundary=02cafbc1d080471284be55dc1095b399'}

我的函数基于 python/django 文档和我在互联网上找到的一些解决方案。功能看起来一样,但不知何故它不起作用。我应该采取不同的方法吗?在 php 中我不需要定义标题等。

【问题讨论】:

    标签: php django http file-upload django-forms


    【解决方案1】:

    嗯,首先我想问一下你为什么要这样做?是因为存储或负载还是故障转移?如果是存储,为什么要通过 HTTP 将文件发送到第二台服务器?我想一个简单的 SSH 文件传输就可以了(scp)。如果是故障转移,您最好使用rsync

    如果不强制使用您自己的第二台服务器,您不妨使用 CDN 服务。

    【讨论】:

    • 规范不允许上传到运行 django 实例的服务器,因此所有静态(包括上传)都保存在单独的媒体服务器上的云中。所以我需要为用户提供一个功能,将文件从表单直接上传到这个服务器。这就是为什么我认为唯一的选择是使用 python 模拟表单或使用一些包装器(如 django-filetransfers)
    • 所以你根本不允许将上传的文件存储在 django 实例上?即使是暂时的?
    • 不确定,但猜测更多的是关于永久存储。因此,甚至可能允许 temp->diskspace->send->remove from discspace。仍然使用内置库,我没有设法用文件创建有效的 POST。目前我正在尝试重写 S3 存储并将其与 temp->disk->send->remove 方法一起使用,因为不允许对 TemporaryUploadedFile 进行读取操作。
    • 我认为这与 Django 无关。也许您可以尝试创建一个 unix 管道,例如 /uploads 并且写入该管道的所有内容都通过 SSH 传输到不同的服务器(或通过其他协议传输到 S3),这很方便,因为您正在执行常规 IO,但是您的系统正在自动执行后台工作。您还可以在输入文件时压缩文件,在输出文件时解压缩,这也将减少网络传输。我在通过服务器传输大型数据库转储时使用了这种技术。
    • 猜猜这个问题过于复杂了。如果只有一种方法可以防止用户被重定向,那么 django-filetransfers 将会非常棒。
    猜你喜欢
    • 1970-01-01
    • 2011-08-27
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    相关资源
    最近更新 更多